5#include <vtkCellData.h>
6#include <vtkDoubleArray.h>
7#include <vtkInformation.h>
8#include <vtkPointData.h>
13int ttkRipsPersistenceDiagram::DiagramToVTU(
14 vtkUnstructuredGrid *vtu,
15 const std::vector<std::vector<ripser::pers_pair_t>> &diagram) {
16 const auto pd = vtu->GetPointData();
17 const auto cd = vtu->GetCellData();
20 for(
auto const &diagram_d : diagram)
21 n_pairs += diagram_d.size();
24 vtkNew<ttkSimplexIdTypeArray> vertsId{};
26 vertsId->SetNumberOfTuples(2 * n_pairs);
27 pd->AddArray(vertsId);
29 vtkNew<vtkIntArray> critType{};
31 critType->SetNumberOfTuples(2 * n_pairs);
32 pd->AddArray(critType);
35 vtkNew<ttkSimplexIdTypeArray> pairsId{};
37 pairsId->SetNumberOfTuples(n_pairs);
38 cd->AddArray(pairsId);
40 vtkNew<vtkIntArray> pairsDim{};
42 pairsDim->SetNumberOfTuples(n_pairs);
43 cd->AddArray(pairsDim);
48 cd->AddArray(persistence);
50 vtkNew<vtkDoubleArray> birthScalars{};
52 birthScalars->SetNumberOfTuples(n_pairs);
53 cd->AddArray(birthScalars);
55 vtkNew<vtkUnsignedCharArray> isFinite{};
57 isFinite->SetNumberOfTuples(n_pairs);
58 cd->AddArray(isFinite);
61 vtkNew<vtkPoints> points{};
62 points->SetNumberOfPoints(2 * n_pairs);
63 vtkNew<vtkIdTypeArray> offsets{}, connectivity{};
64 offsets->SetNumberOfComponents(1);
65 offsets->SetNumberOfTuples(n_pairs + 1);
66 connectivity->SetNumberOfComponents(1);
67 connectivity->SetNumberOfTuples(2 * n_pairs);
71 double birth_max = 0.;
72 for(
unsigned d = 0; d < diagram.size(); ++d) {
73 for(
auto const &pair : diagram[d]) {
74 const unsigned i0 = 2 * i, i1 = 2 * i + 1;
75 pairsId->SetTuple1(i, i);
76 pairsDim->SetTuple1(i, d);
81 pair.second.second < std::numeric_limits<ripser::value_t>::infinity());
82 persistence->SetTuple1(i, death - pair.first.second);
83 birthScalars->SetTuple1(i, pair.first.second);
84 points->SetPoint(i0, pair.first.second, pair.first.second, 0);
85 points->SetPoint(i1, pair.first.second, death, 0);
87 if(pair.first.second > birth_max) {
88 birth_max = pair.first.second;
92 connectivity->SetTuple1(i0, i0);
93 connectivity->SetTuple1(i1, i1);
94 offsets->SetTuple1(i, 2 * i);
96 critType->SetTuple1(i0, d);
97 critType->SetTuple1(i1, d + 1);
99 vertsId->SetTuple1(i0, *std::max_element(pair.first.first.begin(),
100 pair.first.first.end()));
101 vertsId->SetTuple1(i1, *std::max_element(pair.second.first.begin(),
102 pair.second.first.end()));
108 offsets->SetTuple1(n_pairs, connectivity->GetNumberOfTuples());
110 vtkNew<vtkCellArray> cells{};
111 cells->SetData(offsets, connectivity);
112 vtu->SetPoints(points);
113 vtu->SetCells(VTK_LINE, cells);
116 std::array<vtkIdType, 2> diag{0, 2 * i_max};
117 vtu->InsertNextCell(VTK_LINE, 2, diag.data());
118 pairsId->InsertTuple1(n_pairs, -1);
119 pairsDim->InsertTuple1(n_pairs, -1);
120 isFinite->InsertTuple1(n_pairs,
false);
122 birthScalars->InsertTuple1(n_pairs, 0.);
128 this->SetNumberOfInputPorts(1);
129 this->SetNumberOfOutputPorts(1);
133 vtkInformation *info) {
135 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),
"vtkTable");
142 vtkInformation *info) {
144 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkUnstructuredGrid");
151 vtkInformationVector **inputVector,
152 vtkInformationVector *outputVector) {
156 vtkTable *input = vtkTable::GetData(inputVector[0]);
157 vtkUnstructuredGrid *outputPersistenceDiagram
158 = vtkUnstructuredGrid::GetData(outputVector);
163 std::vector<std::vector<double>> points;
165 const int numberOfPoints = input->GetNumberOfRows();
166 const int dimension = input->GetNumberOfColumns();
168 points = std::vector<std::vector<double>>(numberOfPoints);
169 for(
int i = 0; i < numberOfPoints; ++i) {
170 for(
int j = 0; j < dimension; ++j)
171 points[i].push_back(input->GetValue(i, j).ToDouble());
173 this->
printMsg(
"Ripser starts (#dim: " + std::to_string(dimension)
174 +
", #pts: " + std::to_string(numberOfPoints) +
")",
175 1.0, tm.getElapsedTime(), 1);
178 = std::min(input->GetNumberOfRows(), input->GetNumberOfColumns());
179 const int column_offset = input->GetNumberOfColumns() - n;
181 points = {std::vector<double>(n * (n - 1) / 2)};
182 for(
int i = 1; i < n; ++i) {
183 for(
int j = 0; j < i; ++j)
184 points[0][i * (i - 1) / 2 + j]
185 = input->GetValue(i, j + column_offset).ToDouble();
187 this->
printMsg(
"Ripser starts (" + std::to_string(n) +
"x"
188 + std::to_string(n) +
" dist mat)",
189 1.0, tm.getElapsedTime(), 1);
193 1.0, tm.getElapsedTime(), 1);
196 tm.getElapsedTime(), 1);
198 std::vector<std::vector<ripser::pers_pair_t>> diagram(0);
200 const auto ret = this->
execute(points, diagram);
205 DiagramToVTU(outputPersistenceDiagram, diagram);
206 this->
printMsg(
"Complete", 1.0, tm.getElapsedTime(), 1);
209 outputPersistenceDiagram->GetFieldData()->ShallowCopy(input->GetFieldData());
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
TTK VTK-filter that wraps the ttk::RipsPersistenceDiagram module.
ttkRipsPersistenceDiagram()
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int InputIsDistanceMatrix
double SimplexMaximumDiameter
int SimplexMaximumDimension
int execute(const std::vector< std::vector< double > > &points, std::vector< std::vector< ripser::pers_pair_t > > &ph) const
Main entry point.
const char PersistenceName[]
const char PersistencePairTypeName[]
const char PersistenceCriticalTypeName[]
const char PersistenceIsFinite[]
const char VertexScalarFieldName[]
default name for vertex scalar field
const char PersistencePairIdentifierName[]
const char PersistenceBirthName[]
vtkStandardNewMacro(ttkRipsPersistenceDiagram)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)