TTK
Loading...
Searching...
No Matches
ttkTrackingFromFields.cpp
Go to the documentation of this file.
1#include <vtkDoubleArray.h>
2#include <vtkInformation.h>
3#include <vtkPointData.h>
4
5#include <ttkMacros.h>
8#include <ttkUtils.h>
9
11
13 this->SetNumberOfInputPorts(1);
14 this->SetNumberOfOutputPorts(1);
15}
16
18 vtkInformation *info) {
19 if(port == 0) {
20 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid");
21 return 1;
22 }
23 return 0;
24}
26 vtkInformation *info) {
27 if(port == 0) {
28 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
29 return 1;
30 }
31 return 0;
32}
33
34// (*) Persistence-driven approach
35template <class dataType, class triangulationType>
36int ttkTrackingFromFields::trackWithPersistenceMatching(
37 vtkUnstructuredGrid *output,
38 unsigned long fieldNumber,
39 const triangulationType *triangulation) {
40
41 using trackingTuple = ttk::trackingTuple;
42
43 // 1. get persistence diagrams.
44 std::vector<ttk::DiagramType> persistenceDiagrams(fieldNumber);
45
46 this->performDiagramComputation<dataType, triangulationType>(
47 (int)fieldNumber, persistenceDiagrams, triangulation);
48
49 // 2. call feature tracking with threshold.
50 std::vector<std::vector<ttk::MatchingType>> outputMatchings(fieldNumber - 1);
51
52 double spacing = Spacing;
53 std::string algorithm = DistanceAlgorithm;
54 double tolerance = Tolerance;
55 std::string wasserstein = WassersteinMetric;
56
59 tfp.setDebugLevel(this->debugLevel_);
60 tfp.performMatchings(
61 (int)fieldNumber, persistenceDiagrams, outputMatchings,
62 algorithm, // Not from paraview, from enclosing tracking plugin
63 wasserstein, tolerance, PX, PY, PZ, PS, PE // Coefficients
64 );
65
66 vtkNew<vtkPoints> points{};
67 vtkNew<vtkUnstructuredGrid> persistenceDiagram{};
68
69 vtkNew<vtkDoubleArray> persistenceScalars{};
70 vtkNew<vtkDoubleArray> valueScalars{};
71 vtkNew<vtkIntArray> matchingIdScalars{};
72 vtkNew<vtkIntArray> lengthScalars{};
73 vtkNew<vtkIntArray> timeScalars{};
74 vtkNew<vtkIntArray> componentIds{};
75 vtkNew<vtkIntArray> pointTypeScalars{};
76
77 persistenceScalars->SetName("Cost");
78 valueScalars->SetName("Scalar");
79 matchingIdScalars->SetName("MatchingIdentifier");
80 lengthScalars->SetName("ComponentLength");
81 timeScalars->SetName("TimeStep");
82 componentIds->SetName("ConnectedComponentId");
83 pointTypeScalars->SetName("CriticalType");
84
85 // (+ vertex id)
86 std::vector<trackingTuple> trackingsBase;
87 tfp.performTracking(persistenceDiagrams, outputMatchings, trackingsBase);
88
89 std::vector<std::set<int>> trackingTupleToMerged(trackingsBase.size());
90
91 if(DoPostProc) {
92 tfp.performPostProcess(persistenceDiagrams, trackingsBase,
93 trackingTupleToMerged, PostProcThresh);
94 }
95
96 bool useGeometricSpacing = UseGeometricSpacing;
97
98 // Build mesh.
100 trackingsBase, outputMatchings, persistenceDiagrams, useGeometricSpacing,
101 spacing, DoPostProc, trackingTupleToMerged, points, persistenceDiagram,
102 persistenceScalars, valueScalars, matchingIdScalars, lengthScalars,
103 timeScalars, componentIds, pointTypeScalars, *this);
104
105 output->ShallowCopy(persistenceDiagram);
106
107 return 1;
108}
109
111 vtkInformationVector **inputVector,
112 vtkInformationVector *outputVector) {
113
114 auto input = vtkDataSet::GetData(inputVector[0]);
115 auto output = vtkUnstructuredGrid::GetData(outputVector);
116
118 if(!triangulation)
119 return 0;
120
121 this->preconditionTriangulation(triangulation);
122
123 // Test validity of datasets
124 if(input == nullptr || output == nullptr) {
125 return -1;
126 }
127
128 // Get number and list of inputs.
129 std::vector<vtkDataArray *> inputScalarFieldsRaw;
130 std::vector<vtkDataArray *> inputScalarFields;
131 const auto pointData = input->GetPointData();
132 int numberOfInputFields = pointData->GetNumberOfArrays();
133 if(numberOfInputFields < 3) {
134 this->printErr("Not enough input fields to perform tracking.");
135 }
136
137 vtkDataArray *firstScalarField = pointData->GetArray(0);
138
139 for(int i = 0; i < numberOfInputFields; ++i) {
140 vtkDataArray *currentScalarField = pointData->GetArray(i);
141 if(currentScalarField == nullptr
142 || currentScalarField->GetName() == nullptr) {
143 continue;
144 }
145 std::string sfname{currentScalarField->GetName()};
146 if(sfname.rfind("_Order") == (sfname.size() - 6)) {
147 continue;
148 }
149 if(firstScalarField->GetDataType() != currentScalarField->GetDataType()) {
150 this->printErr("Inconsistent field data type or size between fields `"
151 + std::string{firstScalarField->GetName()} + "' and `"
152 + sfname + "'");
153 return -1;
154 }
155 inputScalarFieldsRaw.push_back(currentScalarField);
156 }
157
158 std::sort(inputScalarFieldsRaw.begin(), inputScalarFieldsRaw.end(),
159 [](vtkDataArray *a, vtkDataArray *b) {
160 std::string s1 = a->GetName();
161 std::string s2 = b->GetName();
162 return std::lexicographical_compare(
163 s1.begin(), s1.end(), s2.begin(), s2.end());
164 });
165
166 numberOfInputFields = inputScalarFieldsRaw.size();
167 int end = EndTimestep <= 0 ? numberOfInputFields
168 : std::min(numberOfInputFields, EndTimestep);
169 for(int i = StartTimestep; i < end; i += Sampling) {
170 vtkDataArray *currentScalarField = inputScalarFieldsRaw[i];
171 // Print scalar field names:
172 // std::cout << currentScalarField->GetName() << std::endl;
173 inputScalarFields.push_back(currentScalarField);
174 }
175
176 // Input -> persistence filter.
177 std::string algorithm = DistanceAlgorithm;
178 int pvalg = PVAlgorithm;
179 bool useTTKMethod = false;
180
181 if(pvalg >= 0) {
182 switch(pvalg) {
183 case 0:
184 case 1:
185 case 2:
186 case 3:
187 useTTKMethod = true;
188 break;
189 case 4:
190 break;
191 default:
192 this->printMsg("Unrecognized tracking method.");
193 break;
194 }
195 } else {
196 using ttk::str2int;
197 switch(str2int(algorithm.c_str())) {
198 case str2int("0"):
199 case str2int("ttk"):
200 case str2int("1"):
201 case str2int("legacy"):
202 case str2int("2"):
203 case str2int("geometric"):
204 case str2int("3"):
205 case str2int("parallel"):
206 useTTKMethod = true;
207 break;
208 case str2int("4"):
209 case str2int("greedy"):
210 break;
211 default:
212 this->printMsg("Unrecognized tracking method.");
213 break;
214 }
215 }
216
217 // 0. get data
218 int fieldNumber = inputScalarFields.size();
219 std::vector<void *> inputFields(fieldNumber);
220 for(int i = 0; i < fieldNumber; ++i) {
221 inputFields[i] = ttkUtils::GetVoidPointer(inputScalarFields[i]);
222 }
223 this->setInputScalars(inputFields);
224
225 // 0'. get offsets
226 std::vector<ttk::SimplexId *> inputOrders(fieldNumber);
227 for(int i = 0; i < fieldNumber; ++i) {
228 this->SetInputArrayToProcess(0, 0, 0, 0, inputScalarFields[i]->GetName());
229 auto orderArray = this->GetOrderArray(input, 0, 0, false);
230 inputOrders[i]
231 = static_cast<ttk::SimplexId *>(ttkUtils::GetVoidPointer(orderArray));
232 }
233 this->setInputOffsets(inputOrders);
234
235 int status = 0;
236 if(useTTKMethod) {
238 inputScalarFields[0]->GetDataType(), triangulation->getType(),
239 (status = this->trackWithPersistenceMatching<VTK_TT, TTK_TT>(
240 output, fieldNumber, (TTK_TT *)triangulation->getData())));
241 } else {
242 this->printMsg("The specified matching method is not supported.");
243 }
244
245 return status;
246}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition: BaseClass.h:47
vtkDataArray * GetOrderArray(vtkDataSet *const inputData, const int scalarArrayIdx, const int orderArrayIdx=0, const bool enforceOrderArrayIdx=false)
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
TTK VTK-filter that takes an input time-varying data set (represented by a list of scalar fields) and...
int FillOutputPortInformation(int port, vtkInformation *info) override
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
static int buildMesh(const std::vector< ttk::trackingTuple > &trackings, const std::vector< std::vector< ttk::MatchingType > > &outputMatchings, const std::vector< ttk::DiagramType > &inputPersistenceDiagrams, const bool useGeometricSpacing, const double spacing, const bool doPostProc, const std::vector< std::set< int > > &trackingTupleToMerged, vtkPoints *points, vtkUnstructuredGrid *persistenceDiagram, vtkDoubleArray *persistenceScalars, vtkDoubleArray *valueScalars, vtkIntArray *matchingIdScalars, vtkIntArray *lengthScalars, vtkIntArray *timeScalars, vtkIntArray *componentIds, vtkIntArray *pointTypeScalars, const ttk::Debug &dbg)
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition: ttkUtils.cpp:225
int threadNumber_
Definition: BaseClass.h:95
virtual int setThreadNumber(const int threadNumber)
Definition: BaseClass.h:80
int debugLevel_
Definition: Debug.h:379
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
Definition: Debug.h:118
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition: Debug.h:149
void setInputOffsets(std::vector< SimplexId * > &io)
void preconditionTriangulation(AbstractTriangulation *triangulation)
void setInputScalars(std::vector< void * > &is)
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
Definition: Triangulation.h:48
AbstractTriangulation * getData()
Triangulation::Type getType() const
constexpr unsigned long long str2int(const char *str, int h=0)
std::tuple< int, int, std::vector< SimplexId > > trackingTuple
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22
#define ttkVtkTemplateMacro(dataType, triangulationType, call)
Definition: ttkMacros.h:69
vtkStandardNewMacro(ttkTrackingFromFields)