56int finalize(vector<vector<TrackingFromOverlap::Nodes>> &levelTimeNodesMap,
57 vector<vector<TrackingFromOverlap::Edges>> &levelTimeEdgesTMap,
58 vector<vector<TrackingFromOverlap::Edges>> &timeLevelEdgesNMap,
60 const string &labelFieldName,
62 vtkDataObject *trackingGraphObject) {
63 auto trackingGraph = vtkUnstructuredGrid::SafeDownCast(trackingGraphObject);
65 size_t const nL = levelTimeNodesMap.size();
66 size_t const nT = levelTimeNodesMap[0].size();
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);
78 for(
size_t t = 0; t < nT; t++)
79 for(
size_t l = 0; l < nL; l++)
80 nNodes += levelTimeNodesMap[l][t].size();
83 points->SetNumberOfPoints(nNodes);
87 prepArray(sequence,
"SequenceIndex", 1, nNodes);
91 prepArray(level,
"LevelIndex", 1, nNodes);
95 prepArray(size,
"Size", 1, nNodes);
99 prepArray(branch,
"BranchId", 1, nNodes);
103 vtkDataArray::CreateDataArray(labelTypeId));
104 prepArray(label, labelFieldName, 1, nNodes);
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;
115 sequenceData[q2] = t;
117 sizeData[q2] = node.size;
118 branchData[q2] = node.branchID;
119 labelData[q2] = boost::get<labelType>(node.label);
126 trackingGraph->SetPoints(points);
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);
138 if(nT * nL + 1 <= 0) {
143 vector<size_t> timeLevelOffsetMap(nT * nL + 1);
145 timeLevelOffsetMap[0] = 0;
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();
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;
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;
168 cells->SetNumberOfValues(3 * nEdgesT + 3 * nEdgesN);
172 prepArray(overlap,
"Overlap", 1, nEdgesT + nEdgesN);
176 prepArray(branch,
"BranchId", 1, nEdgesT + nEdgesN);
180 prepArray(type,
"Type", 1, nEdgesT + nEdgesN);
183 size_t q0 = 0, q1 = 0;
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;) {
193 = (vtkIdType)(timeLevelOffsetMap[(t - 1) * nL + l] + edges[i++]);
195 = (vtkIdType)(timeLevelOffsetMap[(t)*nL + l] + edges[i++]);
197 overlapData[q1] = edges[i++];
198 branchData[q1] = edges[i++];
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;) {
213 = (vtkIdType)(timeLevelOffsetMap[temp + (l - 1)] + edges[i++]);
215 = (vtkIdType)(timeLevelOffsetMap[temp + (l)] + edges[i++]);
217 overlapData[q1] = edges[i++];
218 branchData[q1] = edges[i++];
225#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 6, 1)
226 cellArray->ImportLegacyFormat(cells);
228 cellArray->SetCells(nEdgesT + nEdgesN, cells);
230 trackingGraph->SetCells(VTK_LINE, cellArray);
232 auto cellData = trackingGraph->GetCellData();
233 cellData->AddArray(type);
234 cellData->AddArray(overlap);
235 cellData->AddArray(branch);
287 vtkDataObject *inputDataObject, vtkMultiBlockDataSet *packedInput)
const {
305 auto inputAsMB = vtkMultiBlockDataSet::SafeDownCast(inputDataObject);
306 auto inputAsPS = vtkPointSet::SafeDownCast(inputDataObject);
309 size_t const n = inputAsMB->GetNumberOfBlocks();
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);
326 packedInput->ShallowCopy(inputAsMB);
330 for(
size_t i = 0; i < n; i++) {
331 level->SetBlock(i, vtkPointSet::SafeDownCast(inputAsMB->GetBlock(i)));
333 packedInput->SetBlock(0, level);
337 }
else if(inputAsPS) {
339 level->SetBlock(0, inputAsPS);
340 packedInput->SetBlock(0, level);
346 printErr(
"Unable to convert input into "
347 "'vtkPointSet' collection.");
358 size_t const nL = data->GetNumberOfBlocks();
362 printErr(
"Input must have at least one "
367 for(
size_t l = 0; l < nL; l++) {
368 auto timesteps = vtkMultiBlockDataSet::SafeDownCast(data->GetBlock(l));
369 size_t const n = timesteps->GetNumberOfBlocks();
371 printErr(
"Input must have at least one "
378 printErr(
"Timeseries have unequal length.");
382 for(
size_t t = 0; t < nT; t++) {
383 auto pointSet = vtkPointSet::SafeDownCast(timesteps->GetBlock(t));
384 if(pointSet ==
nullptr) {
387 size_t const nPoints = pointSet->GetNumberOfPoints();
388 auto labels = pointSet->GetPointData()->GetAbstractArray(
391 if(nPoints > 0 && labels ==
nullptr) {
395 if(labels ==
nullptr)
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.");
416 vtkMultiBlockDataSet *data)
const {
417 size_t const nL_PI = this->previousIterationData->GetNumberOfBlocks();
418 size_t const nL_CI = streamedData->GetNumberOfBlocks();
420 printErr(
"Number of levels differ over time.");
423 for(
size_t l = 0; l < nL_PI; l++) {
424 auto timestepsPI = vtkMultiBlockDataSet::SafeDownCast(
425 this->previousIterationData->GetBlock(l));
427 = vtkMultiBlockDataSet::SafeDownCast(streamedData->GetBlock(l));
428 size_t const nT_CI = timestepsCI->GetNumberOfBlocks();
433 timesteps->SetBlock(0, timestepsPI->GetBlock(0));
436 for(
size_t t = 0; t < nT_CI; t++)
437 timesteps->SetBlock(t + 1, timestepsCI->GetBlock(t));
439 data->SetBlock(l, timesteps);
479 getNumberOfLevelsAndTimesteps(data, nL, nT);
482 vtkPointSet *pointSet =
nullptr;
483 vtkDataArray *labels =
nullptr;
487 printMsg(
"=======================================================",
491 if(this->levelTimeNodesMap.size() != nL)
492 this->levelTimeNodesMap.resize(nL);
494 for(
size_t l = 0; l < nL; l++) {
496 printMsg(
"-------------------------------------------------------");
498 msg <<
"Level Index: " << l;
502 vector<Nodes> &timeNodesMap = this->levelTimeNodesMap[l];
503 size_t const timeOffset = timeNodesMap.size();
504 timeNodesMap.resize(timeOffset + nT);
506 for(
size_t t = 0; t < nT; t++) {
509 size_t const nPoints = pointSet->GetNumberOfPoints();
513 switch(this->LabelDataType) {
517 timeNodesMap[timeOffset + t]));
523 printMsg(
"-------------------------------------------------------");
542 getNumberOfLevelsAndTimesteps(data, nL, nT);
548 vtkPointSet *pointSet0 =
nullptr;
549 vtkPointSet *pointSet1 =
nullptr;
550 vtkDataArray *labels0 =
nullptr;
551 vtkDataArray *labels1 =
nullptr;
553 printMsg(
"=======================================================",
557 if(this->levelTimeEdgesTMap.size() != nL)
558 this->levelTimeEdgesTMap.resize(nL);
560 for(
size_t l = 0; l < nL; l++) {
562 printMsg(
"-------------------------------------------------------");
564 msg <<
"Level Index: " << l;
568 vector<Edges> &timeEdgesTMap = this->levelTimeEdgesTMap[l];
569 size_t const timeOffset = timeEdgesTMap.size();
570 timeEdgesTMap.resize(timeOffset + nT - 1);
572 for(
size_t t = 1; t < nT; t++) {
576 size_t const nPoints0 = pointSet0->GetNumberOfPoints();
577 size_t const nPoints1 = pointSet1->GetNumberOfPoints();
578 if(nPoints0 < 1 || nPoints1 < 1)
581 switch(this->LabelDataType) {
587 timeEdgesTMap[timeOffset + t - 1]));
593 printMsg(
"-------------------------------------------------------");
595 msg <<
"Tracking graphs computed in " << timer.
getElapsedTime() <<
" s. ("
610 getNumberOfLevelsAndTimesteps(data, nL, nT);
616 vtkPointSet *pointSet0 =
nullptr;
617 vtkPointSet *pointSet1 =
nullptr;
618 vtkDataArray *labels0 =
nullptr;
619 vtkDataArray *labels1 =
nullptr;
621 printMsg(
"=======================================================",
625 size_t const timeOffset = this->timeLevelEdgesNMap.size();
626 this->timeLevelEdgesNMap.resize(timeOffset + nT);
628 for(
size_t t = 0; t < nT; t++) {
630 printMsg(
"-------------------------------------------------------");
632 msg <<
"Time Index: " << t;
636 vector<Edges> &levelEdgesNMap = this->timeLevelEdgesNMap[timeOffset + t];
637 levelEdgesNMap.resize(nL - 1);
639 for(
size_t l = 1; l < nL; l++) {
643 size_t const nPoints0 = pointSet0->GetNumberOfPoints();
644 size_t const nPoints1 = pointSet1->GetNumberOfPoints();
645 if(nPoints0 < 1 || nPoints1 < 1)
648 switch(this->LabelDataType) {
654 levelEdgesNMap[l - 1]));
660 printMsg(
"-------------------------------------------------------");
662 msg <<
"Nesting trees computed in " << timer.
getElapsedTime() <<
" s. ("
688 vtkInformationVector **inputVector,
689 vtkInformationVector *outputVector) {
695 "===================================================================");
700 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
701 auto inputObject = inInfo->Get(vtkDataObject::DATA_OBJECT());
704 auto iterationInformation = vtkDoubleArray::SafeDownCast(
705 inputObject->GetFieldData()->GetAbstractArray(
"_ttk_IterationInfo"));
707 bool const useStreamingOverTime = iterationInformation !=
nullptr;
709 double iteration = 0;
710 double nIterations = 0;
711 if(useStreamingOverTime) {
712 iteration = iterationInformation->GetValue(0);
713 nIterations = iterationInformation->GetValue(1);
717 if(!useStreamingOverTime || iteration == 0)
734 if(useStreamingOverTime && this->previousIterationData !=
nullptr) {
738 data->ShallowCopy(packedInput);
763 if(!useStreamingOverTime || iteration == nIterations - 1) {
765 vtkInformation *outInfo = outputVector->GetInformationObject(0);
766 auto trackingGraph = outInfo->Get(vtkDataObject::DATA_OBJECT());
780 if(!useStreamingOverTime) {
781 printMsg(
"=======================================================");
783 msg <<
"Nested tracking graph generated in " << timer.
getElapsedTime()