9double ttk::TrackingFromCriticalPoints::criticalPointDistance(
10 const std::array<float, 3> &coords_p1,
11 const double &sfValue_p1,
12 const std::array<float, 3> &coords_p2,
13 const double &sfValue_p2,
15 return std::pow(xWeight_ * std::pow(coords_p1[0] - coords_p2[0], p)
16 + yWeight_ * std::pow(coords_p1[1] - coords_p2[1], p)
17 + zWeight_ * std::pow(coords_p1[2] - coords_p2[2], p)
18 + fWeight_ * std::pow(sfValue_p1 - sfValue_p2, p),
24void ttk::TrackingFromCriticalPoints::sortCriticalPoint(
26 const double minimumRelevantPersistence,
27 std::vector<std::array<float, 3>> &maxCoords,
28 std::vector<std::array<float, 3>> &sad_1Coords,
29 std::vector<std::array<float, 3>> &sad_2Coords,
30 std::vector<std::array<float, 3>> &minCoords,
31 std::vector<double> &maxScalar,
32 std::vector<double> &sad_1Scalar,
33 std::vector<double> &sad_2Scalar,
34 std::vector<double> &minScalar,
35 std::vector<SimplexId> &mapMax,
36 std::vector<SimplexId> &mapSad_1,
37 std::vector<SimplexId> &mapSad_2,
38 std::vector<SimplexId> &mapMin) {
39 for(
unsigned int i = 0; i < d.size(); i++) {
40 std::array<float, 3> birthCoords = d[i].birth.coords;
41 std::array<float, 3> deathCoords = d[i].death.coords;
42 if(std::abs(d[i].
persistence()) > minimumRelevantPersistence) {
45 minCoords.push_back(birthCoords);
46 minScalar.push_back(d[i].birth.sfValue);
49 sad_1Coords.push_back(deathCoords);
50 sad_1Scalar.push_back(d[i].death.sfValue);
51 mapSad_1.push_back(i);
54 sad_2Coords.push_back(birthCoords);
55 sad_2Scalar.push_back(d[i].birth.sfValue);
56 mapSad_2.push_back(i);
58 maxCoords.push_back(deathCoords);
59 maxScalar.push_back(d[i].death.sfValue);
63 sad_1Coords.push_back(birthCoords);
64 sad_1Scalar.push_back(d[i].birth.sfValue);
65 mapSad_1.push_back(i);
67 sad_2Coords.push_back(deathCoords);
68 sad_2Scalar.push_back(d[i].death.sfValue);
69 mapSad_2.push_back(i);
76void ttk::TrackingFromCriticalPoints::buildCostMatrix(
77 const std::vector<std::array<float, 3>> &coords_1,
78 const std::vector<double> &sfValues_1,
79 const std::vector<std::array<float, 3>> &coords_2,
80 const std::vector<double> &sfValues_2,
81 const float &costDeathBirth,
82 std::vector<std::vector<double>> &matrix) {
83 int size_1 = coords_1.size();
84 int size_2 = coords_2.size();
85 int matrix_size = (size_1 > 0 && size_2 > 0) ? size_1 + size_2 : 0;
86 for(
int i = 0; i < size_1; i++) {
87 for(
int j = 0; j < size_2; j++) {
88 matrix[i][j] = criticalPointDistance(
89 coords_1[i], sfValues_1[i], coords_2[j], sfValues_2[j]);
92 for(
int i = size_1; i < matrix_size; i++) {
93 for(
int j = 0; j < size_2; j++) {
94 matrix[i][j] = costDeathBirth;
97 for(
int i = 0; i < size_1; i++) {
98 for(
int j = size_2; j < matrix_size; j++) {
99 matrix[i][j] = costDeathBirth;
105 const std::vector<DiagramType> &persistenceDiagrams,
106 std::vector<std::vector<MatchingType>> &maximaMatchings,
107 std::vector<std::vector<MatchingType>> &sad_1_Matchings,
108 std::vector<std::vector<MatchingType>> &sad_2_Matchings,
109 std::vector<std::vector<MatchingType>> &minimaMatchings,
110 std::vector<std::vector<SimplexId>> &maxMap,
111 std::vector<std::vector<SimplexId>> &sad_1Map,
112 std::vector<std::vector<SimplexId>> &sad_2Map,
113 std::vector<std::vector<SimplexId>> &minMap) {
115 int fieldNumber = persistenceDiagrams.size();
117 std::vector<std::vector<std::array<float, 3>>> maxCoords(fieldNumber);
118 std::vector<std::vector<std::array<float, 3>>> sad_1Coords(fieldNumber);
119 std::vector<std::vector<std::array<float, 3>>> sad_2Coords(fieldNumber);
120 std::vector<std::vector<std::array<float, 3>>> minCoords(fieldNumber);
122 std::vector<std::vector<double>> maxScalar(fieldNumber);
123 std::vector<std::vector<double>> sad_1Scalar(fieldNumber);
124 std::vector<std::vector<double>> sad_2Scalar(fieldNumber);
125 std::vector<std::vector<double>> minScalar(fieldNumber);
127#ifdef TTK_ENABLE_OPENMP
128#pragma omp parallel for num_threads(threadNumber_)
130 for(
int i = 0; i < fieldNumber; i++) {
132 double minimumRelevantPersistence{};
133 if(i < fieldNumber - 1) {
134 minimumRelevantPersistence
135 = ttk::TrackingFromCriticalPoints::computeRelevantPersistence(
136 persistenceDiagrams[i], persistenceDiagrams[i + 1]);
138 if(i == fieldNumber - 1) {
139 minimumRelevantPersistence
140 = ttk::TrackingFromCriticalPoints::computeRelevantPersistence(
141 persistenceDiagrams[i - 1], persistenceDiagrams[i]);
143 sortCriticalPoint(persistenceDiagrams[i], minimumRelevantPersistence,
144 maxCoords[i], sad_1Coords[i], sad_2Coords[i],
145 minCoords[i], maxScalar[i], sad_1Scalar[i],
146 sad_2Scalar[i], minScalar[i], maxMap[i], sad_1Map[i],
147 sad_2Map[i], minMap[i]);
150 int n_max = std::accumulate(
151 maxScalar.begin(), maxScalar.end(), 0,
152 [](
int sum,
const std::vector<double> &v) { return sum + v.size(); });
153 int n_sad_1 = std::accumulate(
154 sad_1Scalar.begin(), sad_1Scalar.end(), 0,
155 [](
int sum,
const std::vector<double> &v) { return sum + v.size(); });
156 int n_sad_2 = std::accumulate(
157 sad_2Scalar.begin(), sad_2Scalar.end(), 0,
158 [](
int sum,
const std::vector<double> &v) { return sum + v.size(); });
159 int n_min = std::accumulate(
160 minScalar.begin(), minScalar.end(), 0,
161 [](
int sum,
const std::vector<double> &v) { return sum + v.size(); });
163 this->
printMsg(
"Processing " + std::to_string(n_min) +
" minima");
164 this->
printMsg(
" " + std::to_string(n_sad_1) +
" 1-saddles");
165 this->
printMsg(
" " + std::to_string(n_sad_2) +
" 2-saddles");
166 this->
printMsg(
" " + std::to_string(n_max) +
" maxima");
168#ifdef TTK_ENABLE_OPENMP
169#pragma omp parallel for num_threads(threadNumber_)
171 for(
int i = 0; i < fieldNumber - 1; i++) {
176 persistenceDiagrams[i], persistenceDiagrams[i + 1]);
177 int maxSize = (maxCoords[i].size() > 0 && maxCoords[i + 1].size() > 0)
178 ? maxCoords[i].size() + maxCoords[i + 1].size()
180 int sad_1Size = (sad_1Coords[i].size() > 0 && sad_1Coords[i + 1].size() > 0)
181 ? sad_1Coords[i].size() + sad_1Coords[i + 1].size()
183 int sad_2Size = (sad_2Coords[i].size() > 0 && sad_2Coords[i + 1].size() > 0)
184 ? sad_2Coords[i].size() + sad_2Coords[i + 1].size()
186 int minSize = (minCoords[i].size() > 0 && minCoords[i + 1].size() > 0)
187 ? minCoords[i].size() + minCoords[i + 1].size()
190 std::vector<std::vector<double>> maxMatrix(
191 maxSize, std::vector<double>(maxSize, 0));
192 std::vector<std::vector<double>> sad_1Matrix(
193 sad_1Size, std::vector<double>(sad_1Size, 0));
194 std::vector<std::vector<double>> sad_2Matrix(
195 sad_2Size, std::vector<double>(sad_2Size, 0));
196 std::vector<std::vector<double>> minMatrix(
197 minSize, std::vector<double>(minSize, 0));
199 buildCostMatrix(maxCoords[i], maxScalar[i], maxCoords[i + 1],
200 maxScalar[i + 1], costDeathBirth, maxMatrix);
201 buildCostMatrix(sad_1Coords[i], sad_1Scalar[i], sad_1Coords[i + 1],
202 sad_1Scalar[i + 1], costDeathBirth, sad_1Matrix);
203 buildCostMatrix(sad_2Coords[i], sad_2Scalar[i], sad_2Coords[i + 1],
204 sad_2Scalar[i + 1], costDeathBirth, sad_2Matrix);
205 buildCostMatrix(minCoords[i], minScalar[i], minCoords[i + 1],
206 minScalar[i + 1], costDeathBirth, minMatrix);
208 assignmentSolver(maxMatrix, maximaMatchings[i]);
209 assignmentSolver(sad_1Matrix, sad_1_Matchings[i]);
210 assignmentSolver(sad_2Matrix, sad_2_Matchings[i]);
211 assignmentSolver(minMatrix, minimaMatchings[i]);
215int ttk::TrackingFromCriticalPoints::computeGlobalId(
220 switch(persistenceDiagram[
id].dim) {
223 ? persistenceDiagram[
id].birth.id
224 : persistenceDiagram[
id].death.id);
227 : persistenceDiagram[
id].death.id);
230 : persistenceDiagram[
id].death.id);
235void ttk::TrackingFromCriticalPoints::performTrackingForOneType(
236 const std::vector<DiagramType> &persistenceDiagrams,
237 const std::vector<std::vector<MatchingType>> &matchings,
238 const std::vector<std::vector<SimplexId>> &map,
240 std::vector<trackingTuple> &trackings,
241 std::vector<std::vector<double>> &trackingCosts,
242 std::vector<std::vector<double>> &trackingsInstantPersistences) {
244 int fieldNumber = matchings.size() + 1;
249 std::vector<int> previousStepMap(deathLimitId, -1);
252 for(
unsigned int i = 0; i < matchings[0].size(); i++) {
253 SimplexId endLocalId = std::get<1>(matchings[0][i]);
254 SimplexId startLocalId = std::get<0>(matchings[0][i]);
255 if(endLocalId < deathLimitId && startLocalId < birthLimitId) {
258 persistenceDiagrams[0], currentType, map[0][startLocalId]);
261 persistenceDiagrams[1], currentType, map[1][endLocalId]);
263 std::vector<SimplexId> chain = {startId, endId};
264 std::tuple<int, int, std::vector<SimplexId>> tt
265 = std::make_tuple(0, 1, chain);
266 trackings.push_back(tt);
267 std::vector<double> newEntry{
268 persistenceDiagrams[0][map[0][startLocalId]].persistence(),
269 persistenceDiagrams[1][map[1][endLocalId]].persistence()};
270 trackingsInstantPersistences.push_back(newEntry);
271 std::vector<double> newCostEntry;
272 newCostEntry.push_back(std::get<2>(matchings[0][i]));
274 trackingCosts.push_back(newCostEntry);
276 previousStepMap[std::get<1>(matchings[0][i])] = trackings.size() - 1;
279 for(
int i = 1; i < fieldNumber - 1; i++) {
280 birthLimitId = map[i].size();
281 deathLimitId = map[i + 1].size();
282 sw.resize(deathLimitId, -1);
283 for(
unsigned int j = 0; j < matchings[i].size(); j++) {
284 SimplexId startLocalId = std::get<0>(matchings[i][j]);
285 SimplexId endLocalId = std::get<1>(matchings[i][j]);
287 bool wasPreviouslyMatched =
false;
288 if(startLocalId < birthLimitId)
289 wasPreviouslyMatched = previousStepMap[startLocalId] != -1;
291 bool validPair = startLocalId < birthLimitId && endLocalId < deathLimitId;
293 if(validPair && wasPreviouslyMatched) {
294 int trackingId = previousStepMap[startLocalId];
296 persistenceDiagrams[i + 1], currentType, map[i + 1][endLocalId]);
297 std::get<1>(trackings[trackingId])++;
298 std::get<2>(trackings[trackingId]).push_back(endId);
299 trackingCosts[trackingId].push_back(std::get<2>(matchings[i][j]));
300 trackingsInstantPersistences[trackingId].push_back(
301 persistenceDiagrams[i + 1][map[i + 1][endLocalId]].
persistence());
302 sw[endLocalId] = trackingId;
303 previousStepMap[startLocalId] = -1;
306 else if(validPair && !wasPreviouslyMatched) {
309 persistenceDiagrams[i], currentType, map[i][startLocalId]);
311 persistenceDiagrams[i + 1], currentType, map[i + 1][endLocalId]);
312 std::vector<ttk::SimplexId> chain = {startId, endId};
313 std::tuple<int, int, std::vector<SimplexId>> tt
314 = std::make_tuple(i, i + 1, chain);
315 trackings.push_back(tt);
316 std::vector<double> newCostEntry;
317 newCostEntry.push_back(std::get<2>(matchings[i][j]));
318 trackingCosts.push_back(newCostEntry);
319 std::vector<double> newEntry{
320 persistenceDiagrams[i][map[i][startLocalId]].persistence(),
321 persistenceDiagrams[i + 1][map[i + 1][endLocalId]].persistence()};
322 trackingsInstantPersistences.push_back(newEntry);
323 sw[endLocalId] = trackings.size() - 1;
326 previousStepMap = sw;
332 const std::vector<DiagramType> &persistenceDiagrams,
333 const std::vector<std::vector<MatchingType>> &maximaMatchings,
334 const std::vector<std::vector<MatchingType>> &sad_1_Matchings,
335 const std::vector<std::vector<MatchingType>> &sad_2_Matchings,
336 const std::vector<std::vector<MatchingType>> &minimaMatchings,
337 const std::vector<std::vector<SimplexId>> &maxMap,
338 const std::vector<std::vector<SimplexId>> &sad_1Map,
339 const std::vector<std::vector<SimplexId>> &sad_2Map,
340 const std::vector<std::vector<SimplexId>> &minMap,
341 std::vector<trackingTuple> &allTrackings,
342 std::vector<std::vector<double>> &allTrackingsCosts,
343 std::vector<std::vector<double>> &allTrackingsInstantPersistences,
344 unsigned int (&typesArrayLimits)[3]) {
346 std::vector<ttk::trackingTuple> trackingsMax;
347 std::vector<ttk::trackingTuple> trackingsSad_1;
348 std::vector<ttk::trackingTuple> trackingsSad_2;
349 std::vector<ttk::trackingTuple> trackingsMin;
351 std::vector<std::vector<double>> maxTrackingCost;
352 std::vector<std::vector<double>> sad_1_TrackingCost;
353 std::vector<std::vector<double>> sad_2_TrackingCost;
354 std::vector<std::vector<double>> minTrackingCost;
356 std::vector<std::vector<double>> trackingsInstantPersistencesMax;
357 std::vector<std::vector<double>> trackingsInstantPersistencesSad_1;
358 std::vector<std::vector<double>> trackingsInstantPersistencesSad_2;
359 std::vector<std::vector<double>> trackingsInstantPersistencesMin;
361 performTrackingForOneType(persistenceDiagrams, maximaMatchings, maxMap,
363 maxTrackingCost, trackingsInstantPersistencesMax);
365 allTrackings.end(), trackingsMax.begin(), trackingsMax.end());
367 allTrackingsInstantPersistences.insert(
368 allTrackingsInstantPersistences.end(),
369 trackingsInstantPersistencesMax.begin(),
370 trackingsInstantPersistencesMax.end());
372 allTrackingsCosts.insert(
373 allTrackingsCosts.end(), maxTrackingCost.begin(), maxTrackingCost.end());
374 typesArrayLimits[0] = allTrackings.size();
376 performTrackingForOneType(
378 trackingsSad_1, sad_1_TrackingCost, trackingsInstantPersistencesSad_1);
380 allTrackings.end(), trackingsSad_1.begin(), trackingsSad_1.end());
382 allTrackingsInstantPersistences.insert(
383 allTrackingsInstantPersistences.end(),
384 trackingsInstantPersistencesSad_1.begin(),
385 trackingsInstantPersistencesSad_1.end());
387 allTrackingsCosts.insert(allTrackingsCosts.end(), sad_1_TrackingCost.begin(),
388 sad_1_TrackingCost.end());
389 typesArrayLimits[1] = allTrackings.size();
391 performTrackingForOneType(
393 trackingsSad_2, sad_2_TrackingCost, trackingsInstantPersistencesSad_2);
396 allTrackings.end(), trackingsSad_2.begin(), trackingsSad_2.end());
398 allTrackingsInstantPersistences.insert(
399 allTrackingsInstantPersistences.end(),
400 trackingsInstantPersistencesSad_2.begin(),
401 trackingsInstantPersistencesSad_2.end());
403 allTrackingsCosts.insert(allTrackingsCosts.end(), sad_2_TrackingCost.begin(),
404 sad_2_TrackingCost.end());
405 typesArrayLimits[2] = allTrackings.size();
407 performTrackingForOneType(persistenceDiagrams, minimaMatchings, minMap,
409 minTrackingCost, trackingsInstantPersistencesMin);
412 allTrackings.end(), trackingsMin.begin(), trackingsMin.end());
414 allTrackingsInstantPersistences.insert(
415 allTrackingsInstantPersistences.end(),
416 trackingsInstantPersistencesMin.begin(),
417 trackingsInstantPersistencesMin.end());
419 allTrackingsCosts.insert(
420 allTrackingsCosts.end(), minTrackingCost.begin(), minTrackingCost.end());
423void ttk::TrackingFromCriticalPoints::assignmentSolver(
424 std::vector<std::vector<double>> &costMatrix,
425 std::vector<ttk::MatchingType> &matching) {
426 if(costMatrix.size() > 0) {
427 if(assignmentMethod_ == 0) {
431 solver.
run(matching);
433 }
else if(assignmentMethod_ == 1) {
436 solver.
run(matching);
int run(std::vector< MatchingType > &matchings) override
void setDeltaLim(double delta)
int run(std::vector< MatchingType > &matchings) override
int setInput(std::vector< std::vector< dataType > > &C_) override
virtual int setInput(std::vector< std::vector< dataType > > &C_)
virtual void clearMatrix()
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])
double computeBoundingBoxRadius(const DiagramType &d1, const DiagramType &d2)
int SimplexId
Identifier type for simplices of any dimension.
CriticalType
default value for critical index
std::vector< PersistencePair > DiagramType
Persistence Diagram type as a vector of Persistence pairs.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)