15 double SimplexMaximumDiameter) {
17 const auto pd = vtu->GetPointData();
18 const auto cd = vtu->GetCellData();
21 for(
auto const &diagram_d : diagram)
22 n_pairs += diagram_d.size();
25 double maxFiniteValue = 0.;
26 for(
auto const &diag : diagram) {
27 for(
auto const &[b, d] : diag) {
29 maxFiniteValue = std::max(maxFiniteValue, d.second);
32 SimplexMaximumDiameter = 1.5 * maxFiniteValue;
36 vtkNew<ttkSimplexIdTypeArray> vertsId{};
38 vertsId->SetNumberOfTuples(2 * n_pairs);
39 pd->AddArray(vertsId);
41 vtkNew<vtkIntArray> critType{};
43 critType->SetNumberOfTuples(2 * n_pairs);
44 pd->AddArray(critType);
47 vtkNew<ttkSimplexIdTypeArray> pairsId{};
49 pairsId->SetNumberOfTuples(n_pairs);
50 cd->AddArray(pairsId);
52 vtkNew<vtkIntArray> pairsDim{};
54 pairsDim->SetNumberOfTuples(n_pairs);
55 cd->AddArray(pairsDim);
57 vtkNew<vtkDoubleArray> persistence{};
59 persistence->SetNumberOfTuples(n_pairs);
60 cd->AddArray(persistence);
62 vtkNew<vtkDoubleArray> birthScalars{};
64 birthScalars->SetNumberOfTuples(n_pairs);
65 cd->AddArray(birthScalars);
67 vtkNew<vtkUnsignedCharArray> isFinite{};
69 isFinite->SetNumberOfTuples(n_pairs);
70 cd->AddArray(isFinite);
73 vtkNew<vtkPoints> points{};
74 points->SetNumberOfPoints(2 * n_pairs);
75 vtkNew<vtkIdTypeArray> offsets{}, connectivity{};
76 offsets->SetNumberOfComponents(1);
77 offsets->SetNumberOfTuples(n_pairs + 1);
78 connectivity->SetNumberOfComponents(1);
79 connectivity->SetNumberOfTuples(2 * n_pairs);
83 double birth_max = 0.;
84 for(
unsigned d = 0; d < diagram.size(); ++d) {
85 for(
auto const &pair : diagram[d]) {
86 const unsigned i0 = 2 * i, i1 = 2 * i + 1;
87 pairsId->SetTuple1(i, i);
88 pairsDim->SetTuple1(i, d);
90 const double death = std::min(SimplexMaximumDiameter, pair.second.second);
92 persistence->SetTuple1(i, death - pair.first.second);
93 birthScalars->SetTuple1(i, pair.first.second);
94 points->SetPoint(i0, pair.first.second, pair.first.second, 0);
95 points->SetPoint(i1, pair.first.second, death, 0);
97 if(pair.first.second > birth_max) {
98 birth_max = pair.first.second;
102 connectivity->SetTuple1(i0, i0);
103 connectivity->SetTuple1(i1, i1);
104 offsets->SetTuple1(i, 2 * i);
106 critType->SetTuple1(i0, d);
107 critType->SetTuple1(i1, d + 1);
109 vertsId->SetTuple1(i0, *std::max_element(pair.first.first.begin(),
110 pair.first.first.end()));
111 vertsId->SetTuple1(i1, *std::max_element(pair.second.first.begin(),
112 pair.second.first.end()));
118 offsets->SetTuple1(n_pairs, connectivity->GetNumberOfTuples());
120 vtkNew<vtkCellArray> cells{};
121 cells->SetData(offsets, connectivity);
122 vtu->SetPoints(points);
123 vtu->SetCells(VTK_LINE, cells);
126 std::array<vtkIdType, 2> diag{0, 2 * i_max};
127 vtu->InsertNextCell(VTK_LINE, 2, diag.data());
128 pairsId->InsertTuple1(n_pairs, -1);
129 pairsDim->InsertTuple1(n_pairs, -1);
130 isFinite->InsertTuple1(n_pairs,
false);
131 persistence->InsertTuple1(n_pairs, 0.);
132 birthScalars->InsertTuple1(n_pairs, 0.);
159 vtkInformationVector **inputVector,
160 vtkInformationVector *outputVector) {
164 vtkTable *input = vtkTable::GetData(inputVector[0]);
165 vtkUnstructuredGrid *outputPersistenceDiagram
166 = vtkUnstructuredGrid::GetData(outputVector);
171 if(SelectFieldsWithRegexp) {
173 ScalarFields.clear();
174 const auto n = input->GetNumberOfColumns();
175 for(
int i = 0; i < n; ++i) {
176 const auto &name = input->GetColumnName(i);
177 if(std::regex_match(name, std::regex(RegexpString))) {
178 ScalarFields.emplace_back(name);
183 if(input->GetNumberOfRows() <= 0 || ScalarFields.size() <= 0) {
184 this->
printErr(
"Input matrix has invalid dimensions (rows: "
185 + std::to_string(input->GetNumberOfRows())
186 +
", columns: " + std::to_string(ScalarFields.size()) +
")");
190 std::vector<vtkAbstractArray *> arrays;
191 arrays.reserve(ScalarFields.size());
192 for(
const auto &s : ScalarFields)
193 arrays.push_back(input->GetColumnByName(s.data()));
195 std::vector<std::vector<double>> points;
197 const int numberOfPoints = input->GetNumberOfRows();
198 const int dimension = ScalarFields.size();
200 points = std::vector<std::vector<double>>(numberOfPoints);
201 for(
int i = 0; i < numberOfPoints; ++i) {
202 for(
int j = 0; j < dimension; ++j)
203 points[i].push_back(arrays[j]->GetVariantValue(i).ToDouble());
206 "Computing Rips persistence diagram", 1.0, tm.getElapsedTime(), 1);
207 this->
printMsg(
"#dimensions: " + std::to_string(dimension)
208 +
", #points: " + std::to_string(numberOfPoints),
209 0.0, tm.getElapsedTime(), 1);
211 const unsigned n = input->GetNumberOfRows();
212 if(n != ScalarFields.size()) {
213 this->
printErr(
"Input distance matrix is not squared.");
214 this->
printErr(
"(rows: " + std::to_string(input->GetNumberOfRows())
215 +
", columns: " + std::to_string(ScalarFields.size())
220 points = {std::vector<double>(n * (n - 1) / 2)};
221 for(
unsigned i = 1; i < n; ++i) {
222 for(
unsigned j = 0; j < i; ++j)
223 points[0][i * (i - 1) / 2 + j]
224 = arrays[j]->GetVariantValue(i).ToDouble();
227 "Computing Rips persistence diagram", 1.0, tm.getElapsedTime(), 1);
229 "(" + std::to_string(n) +
"x" + std::to_string(n) +
" distance matrix)",
230 0.0, tm.getElapsedTime(), 1);
235 0.0, tm.getElapsedTime(), 1);
238 tm.getElapsedTime(), 1);
240 this->
printMsg(
"Backend: Ripser", 0.0, tm.getElapsedTime(), 1);
242 this->
printMsg(
"Backend: Geometric", 0.0, tm.getElapsedTime(), 1);
246 if(this->
execute(points, diagram) != 0)
250 outputPersistenceDiagram, diagram,
253 this->
printMsg(
"Complete", 1.0, tm.getElapsedTime(), 1);
256 outputPersistenceDiagram->GetFieldData()->ShallowCopy(input->GetFieldData());