TTK
Loading...
Searching...
No Matches
ttkPersistenceDiagramClustering.cpp
Go to the documentation of this file.
1#include <ttkMacros.h>
4#include <ttkUtils.h>
5
6#include <vtkCellData.h>
7#include <vtkDataArray.h>
8#include <vtkDoubleArray.h>
9#include <vtkFieldData.h>
10#include <vtkFloatArray.h>
11#include <vtkInformation.h>
12#include <vtkIntArray.h>
13#include <vtkMultiBlockDataSet.h>
14#include <vtkNew.h>
15#include <vtkPointData.h>
16#include <vtkUnsignedCharArray.h>
17#include <vtkUnstructuredGrid.h>
18
19using namespace ttk;
20
22
24 SetNumberOfInputPorts(1);
25 SetNumberOfOutputPorts(3);
26}
27
29 int port, vtkInformation *info) {
30 if(port == 0) {
31 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
32 } else {
33 return 0;
34 }
35 return 1;
36}
37
39 int port, vtkInformation *info) {
40 if(port == 0 || port == 1 || port == 2) {
41 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
42 } else {
43 return 0;
44 }
45 return 1;
46}
47
49 needUpdate_ = true;
50 ttkAlgorithm::Modified();
51}
52
54 vtkInformation *ttkNotUsed(request),
55 vtkInformationVector **inputVector,
56 vtkInformationVector *outputVector) {
57
58 auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
59
60 // Flat storage for diagrams extracted from blocks
61 std::vector<vtkUnstructuredGrid *> input;
62
63 // Number of input diagrams
64 int numInputs = 0;
65
66 if(blocks != nullptr) {
67 numInputs = blocks->GetNumberOfBlocks();
68 input.resize(numInputs);
69 for(int i = 0; i < numInputs; ++i) {
70 input[i] = vtkUnstructuredGrid::SafeDownCast(blocks->GetBlock(i));
71 if(this->GetMTime() < input[i]->GetMTime()) {
72 needUpdate_ = true;
73 }
74 }
75 }
76
77 if(numInputs == 0) {
78 this->printErr("No input detected");
79 return 0;
80 }
81 if(numInputs != 2 and NonMatchingWeight != 1.0) {
82 // We need to modify the update of the barycenter by taking into account the
83 // non-matching weight
84 printWrn("Custom weight only supported for pairwise distance.");
85 printWrn("Non-matching weight is set to 1.");
87 }
88
89 // Get output pointers
90 auto output_clusters = vtkMultiBlockDataSet::GetData(outputVector, 0);
91 auto output_centroids = vtkMultiBlockDataSet::GetData(outputVector, 1);
92 auto output_matchings = vtkMultiBlockDataSet::GetData(outputVector, 2);
93
94 if(needUpdate_) {
95 // clear data before computation
96 intermediateDiagrams_ = {};
97 all_matchings_ = {};
98 final_centroids_ = {};
99
100 intermediateDiagrams_.resize(numInputs);
101 all_matchings_.resize(3);
102
103 // store the persistence of every min-max global pair
104 std::vector<double> max_persistences(numInputs);
105
106 for(int i = 0; i < numInputs; i++) {
107 auto &diag{this->intermediateDiagrams_[i]};
108 const auto ret = VTUToDiagram(diag, input[i], *this);
109 if(ret < 0) {
110 this->printErr("Could not read Persistence Diagram");
111 return 0;
112 }
113 if(this->NumberOfClusters > 1) {
114 // duplicate the global min-max pair in 2: one min-saddle pair and
115 // one saddle-max pair
116 diag[0].death.type = ttk::CriticalType::Saddle1;
117 // store the saddle max pair at the vector end
118 diag.emplace_back(diag[0]);
119 diag.back().birth.type = ttk::CriticalType::Saddle1;
120 diag.back().death.type = ttk::CriticalType::Local_maximum;
121 }
122 max_persistences[i] = diag[0].persistence();
123 }
124
125 this->max_dimension_total_
126 = *std::max_element(max_persistences.begin(), max_persistences.end());
127
128 if(this->Method == METHOD::PROGRESSIVE) {
129
130 if(!UseInterruptible) {
131 TimeLimit = 999999999;
132 }
133
134 inv_clustering_ = this->execute(
135 intermediateDiagrams_, final_centroids_, all_matchings_);
136 needUpdate_ = false;
137
138 } else if(this->Method == METHOD::AUCTION) {
139
140 final_centroids_.resize(1);
141 inv_clustering_.resize(numInputs);
142 for(int i_input = 0; i_input < numInputs; i_input++) {
143 inv_clustering_[i_input] = 0;
144 }
145 PersistenceDiagramBarycenter pdBarycenter{};
146
147 const auto wassersteinMetric = std::to_string(WassersteinMetric);
148 pdBarycenter.setWasserstein(wassersteinMetric);
149 pdBarycenter.setMethod(2);
150 pdBarycenter.setNumberOfInputs(numInputs);
151 pdBarycenter.setDeterministic(Deterministic);
152 pdBarycenter.setUseProgressive(UseProgressive);
153 pdBarycenter.setDebugLevel(debugLevel_);
154 pdBarycenter.setThreadNumber(threadNumber_);
155 pdBarycenter.setAlpha(Alpha);
156 pdBarycenter.setLambda(Lambda);
157 pdBarycenter.setNonMatchingWeight(NonMatchingWeight);
158 pdBarycenter.setDeltaLim(DeltaLim);
159 pdBarycenter.execute(
160 intermediateDiagrams_, final_centroids_[0], all_matchings_);
161
162 needUpdate_ = false;
163 }
164 }
165
166 outputClusteredDiagrams(output_clusters, input, this->intermediateDiagrams_,
167 this->all_matchings_, this->inv_clustering_,
168 this->DisplayMethod, this->Spacing,
169 this->max_dimension_total_);
170 outputCentroids(output_centroids, this->final_centroids_,
171 this->all_matchings_, input[0], this->DisplayMethod,
172 this->Spacing, this->max_dimension_total_);
174 output_matchings, this->NumberOfClusters, this->intermediateDiagrams_,
175 this->all_matchings_, this->final_centroids_, this->inv_clustering_,
176 this->DisplayMethod, this->Spacing, this->max_dimension_total_);
177
178 return 1;
179}
180
181static void addCostsAsFieldData(vtkUnstructuredGrid *vtu,
182 const double minSadCost,
183 const double sadSadCost,
184 const double sadMaxCost) {
185
186 // add global matchings cost as FieldData (only 1 tuple per array)
187 vtkNew<vtkDoubleArray> minSad{};
188 minSad->SetName("MinSaddleCost");
189 minSad->SetNumberOfTuples(1);
190 minSad->SetTuple1(0, minSadCost);
191 vtu->GetFieldData()->AddArray(minSad);
192
193 vtkNew<vtkDoubleArray> sadSad{};
194 sadSad->SetName("SaddleSaddleCost");
195 sadSad->SetNumberOfTuples(1);
196 sadSad->SetTuple1(0, sadSadCost);
197 vtu->GetFieldData()->AddArray(sadSad);
198
199 vtkNew<vtkDoubleArray> sadMax{};
200 sadMax->SetName("SaddleMaxCost");
201 sadMax->SetNumberOfTuples(1);
202 sadMax->SetTuple1(0, sadMaxCost);
203 vtu->GetFieldData()->AddArray(sadMax);
204
205 vtkNew<vtkDoubleArray> wass{};
206 wass->SetName("WassersteinDistance");
207 wass->SetNumberOfTuples(1);
208 wass->SetTuple1(0, minSadCost + sadSadCost + sadMaxCost);
209 vtu->GetFieldData()->AddArray(wass);
210}
211
213 vtkMultiBlockDataSet *output,
214 const std::vector<vtkUnstructuredGrid *> &diagsVTU,
215 const std::vector<ttk::DiagramType> &diags,
216 const std::vector<std::vector<std::vector<ttk::MatchingType>>>
217 &matchingsPerCluster,
218 const std::vector<int> &inv_clustering,
219 const DISPLAY dm,
220 const double spacing,
221 const double max_persistence) const {
222
223 // index of diagram in its cluster
224 std::vector<int> diagIdInClust{};
225 // number of diagrams per cluster
226 std::vector<int> clustSize{};
227
228 // prep work for displaying diagrams as cluster stars
229 if(dm == DISPLAY::STARS) {
230 // total number of clusters
231 const auto nClusters
232 = 1 + *std::max_element(inv_clustering.begin(), inv_clustering.end());
233 clustSize.resize(nClusters, 0);
234 diagIdInClust.resize(diagsVTU.size());
235 for(size_t i = 0; i < inv_clustering.size(); ++i) {
236 auto &diagsInClust = clustSize[inv_clustering[i]];
237 diagIdInClust[i] = diagsInClust;
238 diagsInClust++;
239 }
240 }
241
242 output->SetNumberOfBlocks(diagsVTU.size());
243
244 for(size_t i = 0; i < diagsVTU.size(); ++i) {
245 vtkNew<vtkUnstructuredGrid> vtu{};
246 vtu->ShallowCopy(diagsVTU[i]);
247
248 // put clusterId on FieldData (only 1 tuple)
249 vtkNew<vtkIntArray> clusterId{};
250 clusterId->SetName("ClusterId");
251 clusterId->SetNumberOfComponents(1);
252 clusterId->SetNumberOfTuples(1);
253 clusterId->Fill(inv_clustering[i]);
254 vtu->GetFieldData()->AddArray(clusterId);
255
256 // add ClusterID also on PointData?
257 vtkNew<vtkIntArray> cidPD{};
258 cidPD->SetName("ClusterID");
259 cidPD->SetNumberOfComponents(1);
260 cidPD->SetNumberOfTuples(vtu->GetNumberOfPoints());
261 cidPD->Fill(inv_clustering[i]);
262 vtu->GetPointData()->AddArray(cidPD);
263
264 // add Persistence also on PointData?
265 vtkNew<vtkDoubleArray> pointPers{};
266 pointPers->SetName("Persistence");
267 pointPers->SetNumberOfTuples(vtu->GetNumberOfPoints());
268 vtu->GetPointData()->AddArray(pointPers);
269
270 // diagonal uses two existing points
271 for(int j = 0; j < vtu->GetNumberOfCells() - 1; ++j) {
272 const auto persArray = vtu->GetCellData()->GetArray("Persistence");
273 const auto pers = persArray->GetTuple1(j);
274 pointPers->SetTuple1(2 * j + 0, pers);
275 pointPers->SetTuple1(2 * j + 1, pers);
276 }
277
278 const auto cid = inv_clustering[i];
279 const auto &matchings{matchingsPerCluster[cid][i]};
280 double minSadCost{}, sadSadCost{}, sadMaxCost{};
281 const auto &diag{diags[i]};
282
283 for(size_t j = 0; j < matchings.size(); ++j) {
284 const auto &m{matchings[j]};
285 const auto bidderId{std::get<0>(m)};
286
287 // avoid out-of-bound accesses
288 if(bidderId >= static_cast<ttk::SimplexId>(diag.size())) {
289 this->printWrn("Out-of-bounds access averted");
290 continue;
291 }
292
293 if(bidderId > 0) {
294 const auto &p1{diag[bidderId]};
295 if(p1.birth.type == ttk::CriticalType::Local_minimum) {
296 minSadCost += std::get<2>(m);
297 } else if(p1.birth.type == ttk::CriticalType::Saddle1
298 && p1.death.type == ttk::CriticalType::Saddle2) {
299 sadSadCost += std::get<2>(m);
300 } else if(p1.death.type == ttk::CriticalType::Local_maximum) {
301 sadMaxCost += std::get<2>(m);
302 }
303 }
304 }
305
306 addCostsAsFieldData(vtu, minSadCost, sadSadCost, sadMaxCost);
307
308 // translate diagram back to canonical representation
309 ResetDiagramPosition(vtu, *this);
310
311 if(dm == DISPLAY::MATCHINGS && spacing > 0) {
312 // translate diagrams along the Z axis
313 const std::array<double, 3> trans{0, 0, i == 0 ? -spacing : spacing};
314 TranslateDiagram(vtu, trans);
315 output->SetBlock(i, vtu);
316 } else if(dm == DISPLAY::STARS && spacing > 0) {
317 const auto c = inv_clustering[i];
318 const auto angle = 2.0 * M_PI * static_cast<double>(diagIdInClust[i])
319 / static_cast<double>(clustSize[c]);
320 // translate diagrams in the XY plane
321 const std::array<double, 3> trans{
322 3.0 * (spacing + 0.2) * max_persistence * c
323 + spacing * max_persistence * std::cos(angle) + 0.2,
324 spacing * max_persistence * std::sin(angle), 0};
325 TranslateDiagram(vtu, trans);
326 output->SetBlock(i, vtu);
327
328 } else {
329 // add diagram to output multi-block dataset
330 output->SetBlock(i, vtu);
331 }
332 }
333}
334
336 vtkMultiBlockDataSet *output,
337 const std::vector<DiagramType> &final_centroids,
338 const std::vector<std::vector<std::vector<ttk::MatchingType>>>
339 &matchingsPerCluster,
340 vtkUnstructuredGrid *const someInputDiag,
341 const DISPLAY dm,
342 const double spacing,
343 const double max_persistence) const {
344
345 if(final_centroids.size() != matchingsPerCluster.size()) {
346 this->printWrn("Inconsistent matchings vector size");
347 }
348
349 const auto da{
350 someInputDiag->GetCellData()->GetArray(ttk::PersistenceBirthName)};
351 const auto dim{static_cast<int>(someInputDiag->GetCellData()
353 ->GetRange()[1])
354 + 1};
355
356 for(size_t i = 0; i < final_centroids.size(); ++i) {
357 vtkNew<vtkUnstructuredGrid> vtu{};
358 DiagramToVTU(vtu, final_centroids[i], da, *this, dim, false);
359
360 // put clusterId on FieldData (only 1 tuple)
361 vtkNew<vtkIntArray> cid{};
362 cid->SetName("ClusterId");
363 cid->SetNumberOfTuples(1);
364 cid->SetTuple1(0, i);
365 vtu->GetFieldData()->AddArray(cid);
366
367 // add ClusterID also on PointData?
368 vtkNew<vtkIntArray> cidPD{};
369 cidPD->SetName("ClusterID");
370 cidPD->SetNumberOfComponents(1);
371 cidPD->SetNumberOfTuples(vtu->GetNumberOfPoints());
372 cidPD->Fill(i);
373 vtu->GetPointData()->AddArray(cidPD);
374
375 // add Persistence also on PointData?
376 vtkNew<vtkDoubleArray> pointPers{};
377 pointPers->SetName("Persistence");
378 pointPers->SetNumberOfTuples(vtu->GetNumberOfPoints());
379 vtu->GetPointData()->AddArray(pointPers);
380
381 // diagonal uses two existing points
382 for(int j = 0; j < vtu->GetNumberOfCells() - 1; ++j) {
383 const auto persArray = vtu->GetCellData()->GetArray("Persistence");
384 const auto pers = persArray->GetTuple1(j);
385 pointPers->SetTuple1(2 * j + 0, pers);
386 pointPers->SetTuple1(2 * j + 1, pers);
387 }
388
389 double minSadCost{}, sadSadCost{}, sadMaxCost{};
390
391 for(const auto &matchingsPerDiag : matchingsPerCluster[i]) {
392 for(const auto &m : matchingsPerDiag) {
393 const auto goodId{std::get<1>(m)};
394 const auto &p0{final_centroids[i][goodId]};
395 if(p0.birth.type == ttk::CriticalType::Local_minimum) {
396 minSadCost += std::get<2>(m);
397 } else if(p0.birth.type == ttk::CriticalType::Saddle1
398 && p0.death.type == ttk::CriticalType::Saddle2) {
399 sadSadCost += std::get<2>(m);
400 } else if(p0.death.type == ttk::CriticalType::Local_maximum) {
401 sadMaxCost += std::get<2>(m);
402 }
403 }
404 }
405
406 addCostsAsFieldData(vtu, minSadCost, sadSadCost, sadMaxCost);
407
408 if(dm == DISPLAY::STARS && spacing > 0) {
409 // shift centroid along the X axis
410 const std::array<double, 3> trans{
411 3.0 * (spacing + 0.2) * max_persistence * i, 0, 0};
412 TranslateDiagram(vtu, trans);
413 output->SetBlock(i, vtu);
414
415 } else {
416 // add centroid to output multi-block dataset
417 output->SetBlock(i, vtu);
418 }
419 }
420}
421
423 vtkMultiBlockDataSet *output,
424 const size_t nClusters,
425 const std::vector<DiagramType> &diags,
426 const std::vector<std::vector<std::vector<ttk::MatchingType>>>
427 &matchingsPerCluster,
428 const std::vector<DiagramType> &centroids,
429 const std::vector<int> &inv_clustering,
430 const DISPLAY dm,
431 const double spacing,
432 const double max_persistence) const {
433
434 // index of diagram in its cluster
435 std::vector<int> diagIdInClust{};
436 // number of diagrams per cluster
437 std::vector<int> clustSize{};
438
439 // prep work for displaying diagrams as cluster stars
440 if(dm == DISPLAY::STARS) {
441 clustSize.resize(nClusters, 0);
442 diagIdInClust.resize(diags.size());
443 for(size_t i = 0; i < inv_clustering.size(); ++i) {
444 auto &diagsInClust = clustSize[inv_clustering[i]];
445 diagIdInClust[i] = diagsInClust;
446 diagsInClust++;
447 }
448 }
449
450 // count the number of bidders per centroid pair
451 // (when with only 1 cluster and 2 diagrams)
452 std::vector<int> matchings_count(centroids[0].size());
453 std::vector<int> count_to_good{};
454
455 for(size_t i = 0; i < diags.size(); ++i) {
456 const auto cid = inv_clustering[i];
457 const auto &diag{diags[i]};
458 const auto &matchings{matchingsPerCluster[cid][i]};
459
460 vtkNew<vtkUnstructuredGrid> matchingsGrid{};
461
462 const auto nCells{matchings.size()};
463 const auto nPoints{2 * matchings.size()};
464
465 vtkNew<vtkPoints> points{};
466 points->SetNumberOfPoints(nPoints);
467 matchingsGrid->SetPoints(points);
468
469 // point data
470 vtkNew<vtkIntArray> diagIdVerts{};
471 diagIdVerts->SetName("DiagramID");
472 diagIdVerts->SetNumberOfTuples(nPoints);
473 matchingsGrid->GetPointData()->AddArray(diagIdVerts);
474
475 vtkNew<vtkIntArray> pointId{};
476 pointId->SetName("PointID");
477 pointId->SetNumberOfTuples(nPoints);
478 matchingsGrid->GetPointData()->AddArray(pointId);
479
480 // cell data
481 vtkNew<vtkIntArray> diagIdCells{};
482 diagIdCells->SetName("DiagramID");
483 diagIdCells->SetNumberOfTuples(nCells);
484 matchingsGrid->GetCellData()->AddArray(diagIdCells);
485
486 vtkNew<vtkIntArray> clusterId{};
487 clusterId->SetName("ClusterID");
488 clusterId->SetNumberOfTuples(nCells);
489 clusterId->Fill(cid);
490 matchingsGrid->GetCellData()->AddArray(clusterId);
491
492 vtkNew<vtkDoubleArray> matchCost{};
493 matchCost->SetName("Cost");
494 matchCost->SetNumberOfTuples(nCells);
495 matchingsGrid->GetCellData()->AddArray(matchCost);
496
497 vtkNew<vtkIntArray> pairType{};
498 pairType->SetName("PairType");
499 pairType->SetNumberOfTuples(nCells);
500 matchingsGrid->GetCellData()->AddArray(pairType);
501
502 vtkNew<vtkIntArray> isDiagonal{};
503 isDiagonal->SetName("IsDiagonal");
504 isDiagonal->SetNumberOfTuples(nCells);
505 matchingsGrid->GetCellData()->AddArray(isDiagonal);
506
507 for(size_t j = 0; j < matchings.size(); ++j) {
508 const auto &m{matchings[j]};
509 const auto bidderId{std::get<0>(m)};
510 const auto goodId{std::get<1>(m)};
511
512 // avoid out-of-bound accesses
513 if(goodId >= static_cast<ttk::SimplexId>(centroids[cid].size())
514 || bidderId >= static_cast<ttk::SimplexId>(diag.size())) {
515 this->printWrn("Out-of-bounds access averted");
516 continue;
517 }
518
519 if(nClusters == 1) {
520 matchings_count[goodId] += 1;
521 count_to_good.push_back(goodId);
522 }
523
524 const auto &p0{centroids[cid][goodId]};
525 std::array<double, 3> coords1{};
526 std::array<double, 3> coords0{p0.birth.sfValue, p0.death.sfValue, 0};
527
528 if(bidderId >= 0) {
529 const auto &p{diag[bidderId]};
530 coords1[0] = p.birth.sfValue;
531 coords1[1] = p.death.sfValue;
532 coords1[2] = 0;
533 isDiagonal->SetTuple1(j, 0);
534 } else {
535 const double diagonal_projection
536 = (p0.birth.sfValue + p0.death.sfValue) / 2.0;
537 coords1[0] = diagonal_projection;
538 coords1[1] = diagonal_projection;
539 coords1[2] = 0;
540 isDiagonal->SetTuple1(j, 1);
541 }
542
543 if(dm == DISPLAY::STARS && spacing > 0) {
544 const auto angle = 2.0 * M_PI * static_cast<double>(diagIdInClust[i])
545 / static_cast<double>(clustSize[cid]);
546 const auto shift
547 = 3.0 * (std::abs(spacing) + 0.2) * max_persistence * cid;
548 coords0[0] += shift;
549 coords1[0] += shift + spacing * max_persistence * std::cos(angle);
550 coords1[1] += spacing * max_persistence * std::sin(angle);
551
552 } else if(dm == DISPLAY::MATCHINGS) {
553 coords1[2] = (diags.size() == 2 && i == 0) ? -spacing : spacing;
554 }
555
556 points->SetPoint(2 * j + 0, coords0.data());
557 points->SetPoint(2 * j + 1, coords1.data());
558 std::array<vtkIdType, 2> ids{
559 2 * static_cast<vtkIdType>(j) + 0,
560 2 * static_cast<vtkIdType>(j) + 1,
561 };
562 matchingsGrid->InsertNextCell(VTK_LINE, 2, ids.data());
563
564 diagIdCells->SetTuple1(j, i);
565 matchCost->SetTuple1(j, std::get<2>(m));
566 diagIdVerts->SetTuple1(2 * j + 0, i);
567 diagIdVerts->SetTuple1(2 * j + 1, i);
568 pointId->SetTuple1(2 * j + 0, goodId);
569 pointId->SetTuple1(2 * j + 1, bidderId);
570
571 if(bidderId >= 0) {
572 const auto &p1{diag[bidderId]};
573 pairType->SetTuple1(j, p1.isFinite ? p1.dim : -1);
574 } else {
575 pairType->SetTuple1(j, p0.dim);
576 }
577 }
578
579 addCostsAsFieldData(matchingsGrid, this->distances[0], this->distances[1],
580 this->distances[2]);
581
582 // add diagram matchings to multi-block
583 output->SetBlock(i, matchingsGrid);
584 }
585
586 // add matchings number
587 if(nClusters == 1 && diags.size() == 2) {
588 size_t nPrevCells{};
589 for(size_t i = 0; i < diags.size(); ++i) {
590 vtkNew<vtkIntArray> matchNumber{};
591 matchNumber->SetName("MatchNumber");
592 const auto matchings
593 = vtkUnstructuredGrid::SafeDownCast(output->GetBlock(i));
594 const auto nCells = matchings->GetNumberOfCells();
595 matchNumber->SetNumberOfTuples(nCells);
596 for(int j = 0; j < nCells; j++) {
597 const auto goodId = count_to_good[j + (i == 0 ? 0 : nPrevCells)];
598 matchNumber->SetTuple1(j, matchings_count[goodId]);
599 }
600 matchings->GetCellData()->AddArray(matchNumber);
601 nPrevCells = nCells;
602 }
603 }
604}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
#define M_PI
Definition Os.h:50
TTK processing package for the computation of Wasserstein barycenters and K-Means clusterings of a se...
int FillInputPortInformation(int port, vtkInformation *info) override
void outputCentroids(vtkMultiBlockDataSet *output, const std::vector< ttk::DiagramType > &final_centroids, const std::vector< std::vector< std::vector< ttk::MatchingType > > > &matchingsPerCluster, vtkUnstructuredGrid *const someInputDiag, const DISPLAY dm, const double spacing, const double max_persistence) const
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillOutputPortInformation(int port, vtkInformation *info) override
void outputClusteredDiagrams(vtkMultiBlockDataSet *output, const std::vector< vtkUnstructuredGrid * > &diagsVTU, const std::vector< ttk::DiagramType > &diags, const std::vector< std::vector< std::vector< ttk::MatchingType > > > &matchingsPerCluster, const std::vector< int > &inv_clustering, const DISPLAY dm, const double spacing, const double max_persistence) const
void outputMatchings(vtkMultiBlockDataSet *output, const size_t nClusters, const std::vector< ttk::DiagramType > &diags, const std::vector< std::vector< std::vector< ttk::MatchingType > > > &matchingsPerCluster, const std::vector< ttk::DiagramType > &centroids, const std::vector< int > &inv_clustering, const ttkPersistenceDiagramClustering::DISPLAY dm, const double spacing, const double max_persistence) const
int debugLevel_
Definition Debug.h:379
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
std::vector< int > execute(std::vector< DiagramType > &intermediateDiagrams, std::vector< DiagramType > &centroids, std::vector< std::vector< std::vector< MatchingType > > > &all_matchings)
std::string to_string(__int128)
Definition ripserpy.cpp:99
The Topology ToolKit.
const char PersistencePairTypeName[]
Definition DataTypes.h:73
const char PersistenceBirthName[]
Definition DataTypes.h:68
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkPersistenceDiagramClustering)
int DiagramToVTU(vtkUnstructuredGrid *vtu, const ttk::DiagramType &diagram, vtkDataArray *const inputScalars, const ttk::Debug &dbg, const int dim, const bool embedInDomain)
Converts a Persistence Diagram in the ttk::DiagramType format to the VTK Unstructured Grid format (as...
int TranslateDiagram(vtkUnstructuredGrid *const diagram, const std::array< double, 3 > &trans)
Translate a diagram to a new position.
int VTUToDiagram(ttk::DiagramType &diagram, vtkUnstructuredGrid *vtu, const ttk::Debug &dbg)
Converts a Persistence Diagram in the VTK Unstructured Grid format (as generated by the ttkPersistenc...
int ResetDiagramPosition(vtkUnstructuredGrid *const diagram, const ttk::Debug &dbg)
Translate back a canonical diagram into its original position.