1#include <vtkDoubleArray.h>
2#include <vtkInformation.h>
3#include <vtkPointData.h>
13 this->SetNumberOfInputPorts(1);
14 this->SetNumberOfOutputPorts(1);
18 vtkInformation *info) {
20 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkUnstructuredGrid");
26 vtkInformation *info) {
28 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
35template <
class dataType,
class triangulationType>
36int ttkTrackingFromFields::trackWithPersistenceMatching(
37 vtkUnstructuredGrid *output,
38 unsigned long fieldNumber,
39 const triangulationType *triangulation) {
41 std::vector<ttk::DiagramType> persistenceDiagrams(fieldNumber);
44 (
int)fieldNumber, persistenceDiagrams, triangulation);
46 std::vector<std::vector<ttk::MatchingType>> outputMatchings(fieldNumber - 1);
48 double const spacing = Spacing;
49 std::string
const algorithm = DistanceAlgorithm;
50 double const tolerance = Tolerance;
51 std::string
const wasserstein = WassersteinMetric;
57 (
int)fieldNumber, persistenceDiagrams, outputMatchings,
59 wasserstein, tolerance, PX, PY, PZ, PS, PE
62 vtkNew<vtkPoints>
const points{};
63 vtkNew<vtkUnstructuredGrid>
const persistenceDiagram{};
65 vtkNew<vtkDoubleArray> persistenceScalars{};
66 vtkNew<vtkDoubleArray> valueScalars{};
67 vtkNew<vtkIntArray> matchingIdScalars{};
68 vtkNew<vtkIntArray> lengthScalars{};
69 vtkNew<vtkIntArray> timeScalars{};
70 vtkNew<vtkIntArray> componentIds{};
71 vtkNew<vtkIntArray> pointTypeScalars{};
73 persistenceScalars->SetName(
"Cost");
74 valueScalars->SetName(
"Scalar");
75 matchingIdScalars->SetName(
"MatchingIdentifier");
76 lengthScalars->SetName(
"ComponentLength");
77 timeScalars->SetName(
"TimeStep");
78 componentIds->SetName(
"ConnectedComponentId");
79 pointTypeScalars->SetName(
"CriticalType");
81 std::vector<ttk::trackingTuple> trackingsBase;
82 tfp.performTracking(persistenceDiagrams, outputMatchings, trackingsBase);
84 std::vector<std::set<int>> trackingTupleToMerged(trackingsBase.size());
87 tfp.performPostProcess(persistenceDiagrams, trackingsBase,
88 trackingTupleToMerged, PostProcThresh);
91 bool const useGeometricSpacing = UseGeometricSpacing;
95 trackingsBase, outputMatchings, persistenceDiagrams, useGeometricSpacing,
96 spacing, DoPostProc, trackingTupleToMerged, points, persistenceDiagram,
97 persistenceScalars, valueScalars, matchingIdScalars, lengthScalars,
98 timeScalars, componentIds, pointTypeScalars, *
this);
100 output->ShallowCopy(persistenceDiagram);
105template <
class dataType,
class triangulationType>
106int ttkTrackingFromFields::trackWithCriticalPointMatching(
107 vtkUnstructuredGrid *output,
108 unsigned long fieldNumber,
109 const triangulationType *triangulation) {
113 float x = 0, y = 0, z = 0;
114 float maxX = 0, minX = 0, maxY = 0, minY = 0, maxZ = 0, minZ = 0;
115 triangulation->getVertexPoint(0, minX, minY, minZ);
116 triangulation->getVertexPoint(0, maxX, maxY, maxZ);
118 for(
int i = 0; i < triangulation->getNumberOfVertices(); i++) {
119 triangulation->getVertexPoint(i, x, y, z);
120 maxX = std::max(x, maxX);
121 maxX = std::min(x, minX);
122 maxY = std::max(y, maxX);
123 minY = std::min(y, minY);
124 maxZ = std::max(z, maxZ);
125 minZ = std::min(z, minZ);
128 double const relativeDestructionCost = RelativeDestructionCost;
129 double const tolerance = (double)Tolerance;
131 = std::sqrt(std::pow(maxX - minX, 2) + std::pow(maxY - minY, 2)
132 + std::pow(maxZ - minZ, 2));
133 int assignmentMethod = AssignmentMethod;
135 ttk::TrackingFromCriticalPoints tracker;
146 std::vector<ttk::DiagramType> persistenceDiagrams(fieldNumber);
148 (
int)fieldNumber, persistenceDiagrams, triangulation);
151 double previousStepTime = t.getElapsedTime();
153 std::vector<std::vector<ttk::MatchingType>> maximaMatchings(fieldNumber - 1);
154 std::vector<std::vector<ttk::MatchingType>> sad_1_Matchings(fieldNumber - 1);
155 std::vector<std::vector<ttk::MatchingType>> sad_2_Matchings(fieldNumber - 1);
156 std::vector<std::vector<ttk::MatchingType>> minimaMatchings(fieldNumber - 1);
158 std::vector<std::vector<ttk::SimplexId>> maxMap(fieldNumber);
159 std::vector<std::vector<ttk::SimplexId>> sad_1Map(fieldNumber);
160 std::vector<std::vector<ttk::SimplexId>> sad_2Map(fieldNumber);
161 std::vector<std::vector<ttk::SimplexId>> minMap(fieldNumber);
164 sad_1_Matchings, sad_2_Matchings, minimaMatchings,
165 maxMap, sad_1Map, sad_2Map, minMap);
167 this->
printMsg(
"Matchings computed", 1, t.getElapsedTime() - previousStepTime,
169 previousStepTime = t.getElapsedTime();
171 vtkNew<vtkPoints>
const points{};
172 vtkNew<vtkUnstructuredGrid>
const outputMesh{};
174 vtkNew<vtkDoubleArray> costs{};
175 vtkNew<vtkDoubleArray> averagePersistences{};
176 vtkNew<vtkDoubleArray> integratedPersistences{};
177 vtkNew<vtkDoubleArray> maximalPersistences{};
178 vtkNew<vtkDoubleArray> minimalPersistences{};
179 vtkNew<vtkDoubleArray> instantPersistences{};
180 vtkNew<vtkDoubleArray> valueScalars{};
181 vtkNew<vtkIntArray> globalVertexIds{};
182 vtkNew<vtkIntArray> lengthScalars{};
183 vtkNew<vtkIntArray> timeScalars{};
184 vtkNew<vtkIntArray> connectedComponentIds{};
185 vtkNew<vtkIntArray> pointsCriticalType{};
187 costs->SetName(
"Costs");
188 averagePersistences->SetName(
"AveragePersistence");
189 integratedPersistences->SetName(
"IntegratedPersistence");
190 maximalPersistences->SetName(
"MaximalPersistence");
191 minimalPersistences->SetName(
"MinimalPersistence");
192 instantPersistences->SetName(
"InstantPersistence");
193 valueScalars->SetName(
"Scalar");
194 globalVertexIds->SetName(
"VertexGlobalId");
195 lengthScalars->SetName(
"ComponentLength");
196 timeScalars->SetName(
"TimeStep");
197 connectedComponentIds->SetName(
"ConnectedComponentId");
198 pointsCriticalType->SetName(
"CriticalType");
200 std::vector<ttk::trackingTuple> allTrackings;
201 std::vector<std::vector<double>> allTrackingsCosts;
202 std::vector<std::vector<double>> allTrackingsInstantPersistence;
204 unsigned int typesArrayLimits[3] = {};
207 persistenceDiagrams, maximaMatchings, sad_1_Matchings, sad_2_Matchings,
208 minimaMatchings, maxMap, sad_1Map, sad_2Map, minMap, allTrackings,
209 allTrackingsCosts, allTrackingsInstantPersistence, typesArrayLimits);
211 this->
printMsg(
"Trackings computed", 1, t.getElapsedTime() - previousStepTime,
213 previousStepTime = t.getElapsedTime();
215 double const spacing = Spacing;
216 bool const useGeometricSpacing = UseGeometricSpacing;
219 triangulation, allTrackings, allTrackingsCosts,
220 allTrackingsInstantPersistence, useGeometricSpacing, spacing, points,
221 outputMesh, pointsCriticalType, timeScalars, lengthScalars, globalVertexIds,
222 connectedComponentIds, costs, averagePersistences, integratedPersistences,
223 maximalPersistences, minimalPersistences, instantPersistences,
227 "Mesh built", 1, t.getElapsedTime() - previousStepTime,
threadNumber_);
228 this->
printMsg(
"Total run time ", 1, t.getElapsedTime(), this->threadNumber_);
230 output->ShallowCopy(outputMesh);
236 vtkInformationVector **inputVector,
237 vtkInformationVector *outputVector) {
239 auto input = vtkDataSet::GetData(inputVector[0]);
240 auto output = vtkUnstructuredGrid::GetData(outputVector);
248 if(input ==
nullptr || output ==
nullptr) {
253 std::vector<vtkDataArray *> inputScalarFieldsRaw;
254 std::vector<vtkDataArray *> inputScalarFields;
255 const auto pointData = input->GetPointData();
256 int numberOfInputFields = pointData->GetNumberOfArrays();
257 if(numberOfInputFields < 3) {
258 this->
printErr(
"Not enough input fields to perform tracking.");
261 vtkDataArray *firstScalarField = pointData->GetArray(0);
263 for(
int i = 0; i < numberOfInputFields; ++i) {
264 vtkDataArray *currentScalarField = pointData->GetArray(i);
265 if(currentScalarField ==
nullptr
266 || currentScalarField->GetName() ==
nullptr) {
269 std::string
const sfname{currentScalarField->GetName()};
270 if(sfname.rfind(
"_Order") == (sfname.size() - 6)) {
273 if(firstScalarField->GetDataType() != currentScalarField->GetDataType()) {
274 this->
printErr(
"Inconsistent field data type or size between fields `"
275 + std::string{firstScalarField->GetName()} +
"' and `"
279 inputScalarFieldsRaw.push_back(currentScalarField);
282 std::sort(inputScalarFieldsRaw.begin(), inputScalarFieldsRaw.end(),
283 [](vtkDataArray *a, vtkDataArray *b) {
284 std::string s1 = a->GetName();
285 std::string s2 = b->GetName();
286 return std::lexicographical_compare(
287 s1.begin(), s1.end(), s2.begin(), s2.end());
290 numberOfInputFields = inputScalarFieldsRaw.size();
291 int const end = EndTimestep <= 0 ? numberOfInputFields
292 : std::min(numberOfInputFields, EndTimestep);
293 for(
int i = StartTimestep; i <
end; i += Sampling) {
294 vtkDataArray *currentScalarField = inputScalarFieldsRaw[i];
297 inputScalarFields.push_back(currentScalarField);
301 std::string
const algorithm = DistanceAlgorithm;
302 int const pvalg = PVAlgorithm;
303 bool useTTKMethod =
false;
304 bool trackWithCriticalPoints = (pvalg == 2);
317 this->
printMsg(
"Unrecognized tracking method.");
322 switch(str2int(algorithm.c_str())) {
326 case str2int(
"legacy"):
328 case str2int(
"geometric"):
330 case str2int(
"parallel"):
334 case str2int(
"greedy"):
337 this->
printMsg(
"Unrecognized tracking method.");
343 int const fieldNumber = inputScalarFields.size();
344 std::vector<void *> inputFields(fieldNumber);
345 for(
int i = 0; i < fieldNumber; i++) {
351 std::vector<ttk::SimplexId *> inputOrders(fieldNumber);
352 for(
int i = 0; i < fieldNumber; ++i) {
353 this->SetInputArrayToProcess(0, 0, 0, 0, inputScalarFields[i]->GetName());
355 = this->
GetOrderArray(input, 0, triangulation,
false, 0,
false);
362 this->
printMsg(
"Tracking trajectories over " + std::to_string(fieldNumber)
364 if(useTTKMethod && !trackWithCriticalPoints) {
366 inputScalarFields[0]->GetDataType(), triangulation->
getType(),
367 (status = this->trackWithPersistenceMatching<VTK_TT, TTK_TT>(
368 output, fieldNumber, (TTK_TT *)triangulation->
getData())));
369 }
else if(useTTKMethod && trackWithCriticalPoints) {
371 inputScalarFields[0]->GetDataType(), triangulation->
getType(),
372 (status = this->trackWithCriticalPointMatching<VTK_TT, TTK_TT>(
373 output, fieldNumber, (TTK_TT *)triangulation->
getData())));
375 this->
printMsg(
"The specified matching method is not supported.");
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
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 buildMeshAlt(const triangulationType *triangulation, const std::vector< ttk::trackingTuple > &trackings, const std::vector< std::vector< double > > &allTrackingsCosts, const std::vector< std::vector< double > > &allTrackingsInstantPersistence, const bool useGeometricSpacing, const double spacing, vtkPoints *points, vtkUnstructuredGrid *outputMesh, vtkIntArray *pointsCriticalType, vtkIntArray *timeScalars, vtkIntArray *lengthScalars, vtkIntArray *globalVertexIds, vtkIntArray *connectedComponentIds, vtkDoubleArray *costs, vtkDoubleArray *averagePersistence, vtkDoubleArray *integratedPersistence, vtkDoubleArray *maximalPersistence, vtkDoubleArray *minimalPersistence, vtkDoubleArray *instantPersistence, unsigned int *sizes)
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)
virtual int setThreadNumber(const int threadNumber)
virtual int setDebugLevel(const int &debugLevel)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void setAssignmentPrecision(double p)
void setMeshDiameter(double r)
void setTolerance(double t)
void setAssignmentMethod(int a)
void setWeights(double PX, double PY, double PZ, double PF)
void performMatchings(const std::vector< DiagramType > &persistenceDiagrams, std::vector< std::vector< MatchingType > > &maximaMatchings, std::vector< std::vector< MatchingType > > &sad_1_Matchings, std::vector< std::vector< MatchingType > > &sad_2_Matchings, std::vector< std::vector< MatchingType > > &minimaMatchings, std::vector< std::vector< SimplexId > > &maxMap, std::vector< std::vector< SimplexId > > &sad_1Map, std::vector< std::vector< SimplexId > > &sad_2Map, std::vector< std::vector< SimplexId > > &minMap)
void performTrackings(const std::vector< DiagramType > &persistenceDiagrams, const std::vector< std::vector< MatchingType > > &maximaMatchings, const std::vector< std::vector< MatchingType > > &sad_1_Matchings, const std::vector< std::vector< MatchingType > > &sad_2_Matchings, const std::vector< std::vector< MatchingType > > &minimaMatchings, const std::vector< std::vector< SimplexId > > &maxMap, const std::vector< std::vector< SimplexId > > &sad_1Map, const std::vector< std::vector< SimplexId > > &sad_2Map, const std::vector< std::vector< SimplexId > > &minMap, std::vector< trackingTuple > &allTrackings, std::vector< std::vector< double > > &allTrackingsCost, std::vector< std::vector< double > > &allTrackingsInstantPersistences, unsigned int(&typesArrayLimits)[3])
void setEpsilon(double e)
void setInputOffsets(std::vector< SimplexId * > &io)
void preconditionTriangulation(AbstractTriangulation *triangulation)
void setInputScalars(std::vector< void * > &is)
int performDiagramComputation(int fieldNumber, std::vector< ttk::DiagramType > &persistenceDiagrams, const triangulationType *triangulation)
Triangulation is a class that provides time and memory efficient traversal methods on triangulations ...
AbstractTriangulation * getData()
Triangulation::Type getType() const
int SimplexId
Identifier type for simplices of any dimension.
constexpr unsigned long long str2int(const char *str, int h=0)
T end(std::pair< T, T > &p)
#define ttkVtkTemplateMacro(dataType, triangulationType, call)
vtkStandardNewMacro(ttkTrackingFromFields)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)