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 const spacing = Spacing;
53 std::string const algorithm = DistanceAlgorithm;
54 double const tolerance = Tolerance;
55 std::string const 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> const points{};
67 vtkNew<vtkUnstructuredGrid> const 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 const 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 const 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 const 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 const algorithm = DistanceAlgorithm;
178 int const 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 const 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
230 = this->GetOrderArray(input, 0, triangulation, false, 0, false);
231 inputOrders[i]
232 = static_cast<ttk::SimplexId *>(ttkUtils::GetVoidPointer(orderArray));
233 }
234 this->setInputOffsets(inputOrders);
235
236 int status = 0;
237 if(useTTKMethod) {
239 inputScalarFields[0]->GetDataType(), triangulation->getType(),
240 (status = this->trackWithPersistenceMatching<VTK_TT, TTK_TT>(
241 output, fieldNumber, (TTK_TT *)triangulation->getData())));
242 } else {
243 this->printMsg("The specified matching method is not supported.");
244 }
245
246 return status;
247}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
vtkDataArray * GetOrderArray(vtkDataSet *const inputData, const int scalarArrayIdx, ttk::Triangulation *triangulation, const bool getGlobalOrder=false, const int orderArrayIdx=0, const bool enforceOrderArrayIdx=false)
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:226
virtual int setThreadNumber(const int threadNumber)
Definition BaseClass.h:80
int debugLevel_
Definition Debug.h:379
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 ...
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
T end(std::pair< T, T > &p)
Definition ripserpy.cpp:483
#define ttkVtkTemplateMacro(dataType, triangulationType, call)
Definition ttkMacros.h:69
vtkStandardNewMacro(ttkTrackingFromFields)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)