TTK
Loading...
Searching...
No Matches
ttkPersistenceDiagramDictionaryDecoding.cpp
Go to the documentation of this file.
2
3#include <vtkAbstractArray.h>
4#include <vtkInformation.h>
5
6#include <vtkCellData.h>
7#include <vtkCharArray.h>
8#include <vtkDataArray.h>
9#include <vtkDataSet.h>
10#include <vtkDoubleArray.h>
11#include <vtkFiltersCoreModule.h>
12#include <vtkFloatArray.h>
13#include <vtkNew.h>
14#include <vtkObjectFactory.h>
15#include <vtkPointData.h>
16#include <vtkVariantArray.h>
17
19
20#include <ttkMacros.h>
21#include <ttkUtils.h>
22
24
27 this->SetNumberOfInputPorts(2);
28 this->SetNumberOfOutputPorts(2);
29}
30
32 int port, vtkInformation *info) {
33 if(port == 0) {
34 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
35 return 1;
36 } else if(port == 1) {
37 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
38 return 1;
39 } else {
40 return 0;
41 }
42}
43
45 int port, vtkInformation *info) {
46 if(port == 0) {
47 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet");
48 return 1;
49 } else if(port == 1) {
50 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTable");
51 return 1;
52 } else {
53 return 0;
54 }
55}
56
58 vtkInformation * /*request*/,
59 vtkInformationVector **inputVector,
60 vtkInformationVector *outputVector) {
61
62 const auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0]);
63 const auto weightsVTK = vtkTable::GetData(inputVector[1]);
64
65 std::vector<vtkUnstructuredGrid *> inputDiagrams;
66
67 if(blocks != nullptr) {
68 int numInputs = blocks->GetNumberOfBlocks();
69 inputDiagrams.resize(numInputs);
70 for(int i = 0; i < numInputs; ++i) {
71 inputDiagrams[i] = vtkUnstructuredGrid::SafeDownCast(blocks->GetBlock(i));
72 }
73 }
74
75 const size_t nDiags = inputDiagrams.size();
76
77 std::vector<ttk::DiagramType> dictDiagrams(nDiags);
78 for(size_t i = 0; i < nDiags; ++i) {
79 vtkNew<vtkUnstructuredGrid> vtu;
80 vtu->DeepCopy(inputDiagrams[i]);
81 auto &atom = dictDiagrams[i];
82 const auto ret = VTUToDiagram(atom, vtu, *this);
83 if(ret != 0) {
84 this->printWrn("Could not read Persistence Diagram");
85 }
86 }
87
88 // Sanity check
89 for(const auto vtu : inputDiagrams) {
90 if(vtu == nullptr) {
91 this->printErr("Input diagrams are not all vtkUnstructuredGrid");
92 return 0;
93 }
94 }
95
96 const auto zeroPad
97 = [](std::string &colName, const size_t numberCols, const size_t colIdx) {
98 std::string max{std::to_string(numberCols - 1)};
99 std::string cur{std::to_string(colIdx)};
100 std::string zer(max.size() - cur.size(), '0');
101 colName.append(zer).append(cur);
102 };
103
104 vtkNew<vtkTable> temp;
105 temp->DeepCopy(weightsVTK);
106 std::vector<vtkDataArray *> inputWeights;
107 int numWeights = temp->GetNumberOfRows();
108
109 if(weightsVTK != nullptr) {
110 inputWeights.resize(nDiags);
111 for(size_t i = 0; i < nDiags; ++i) {
112 std::string name{"Atom"};
113 zeroPad(name, nDiags, i);
114 inputWeights[i]
115 = vtkDataArray::SafeDownCast(temp->GetColumnByName(name.c_str()));
116 }
117 }
118
119 std::vector<std::vector<double>> vectorWeights(numWeights);
120 for(int i = 0; i < numWeights; ++i) {
121 std::vector<double> &t1 = vectorWeights[i];
122 for(size_t j = 0; j < nDiags; ++j) {
123 double weight = inputWeights[j]->GetTuple1(i);
124 t1.push_back(weight);
125 }
126 }
127 std::vector<ttk::DiagramType> Barycenters(numWeights);
128
129 if(!ComputePoints) {
130 this->execute(dictDiagrams, vectorWeights, Barycenters);
131 }
132
133 auto outputDgm = vtkMultiBlockDataSet::GetData(outputVector, 0);
134 auto outputCoordinates = vtkTable::GetData(outputVector, 1);
135 outputDgm->SetNumberOfBlocks(numWeights);
136 outputCoordinates->SetNumberOfRows(numWeights);
137
138 GetOutputDiagrams(outputDgm, outputCoordinates, Barycenters, dictDiagrams,
139 weightsVTK, vectorWeights, Spacing, 1);
140
141 // Get input object from input vector
142 // Note: has to be a vtkDataSet as required by FillInputPortInformation
143
144 // make a SHALLOW copy of the input
145 // outputDataSet->ShallowCopy(inputDataSet);
146
147 // add to the output point data the computed output array
148 // outputDataSet->GetPointData()->AddArray(outputArray);
149
150 // return success
151 return 1;
152}
153
155 vtkMultiBlockDataSet *output,
156 vtkTable *outputCoordinates,
157 const std::vector<ttk::DiagramType> &diags,
158 std::vector<ttk::DiagramType> &atoms,
159 vtkTable *weightsVTK,
160 const std::vector<std::vector<double>> &weights,
161 const double spacing,
162 const double maxPersistence) const {
163
164 const auto nDiags = diags.size();
165 const auto nAtoms = atoms.size();
166
167 ttk::SimplexId n_existing_blocks = ShowAtoms ? nAtoms : 0;
168
169 output->SetNumberOfBlocks(nDiags + n_existing_blocks);
170 std::vector<std::array<double, 3>> coords(nAtoms);
171 std::vector<std::array<double, 3>> trueCoords(nAtoms);
172 std::vector<double> xVector(nDiags);
173 std::vector<double> yVector(nDiags);
174 std::vector<double> zVector(nDiags, 0.);
175 vtkNew<vtkDoubleArray> dummy{};
176
177 computeAtomsCoordinates(atoms, weights, coords, trueCoords, xVector, yVector,
178 zVector, spacing, nAtoms);
179
180 if(nAtoms == 2) {
181
182 if(ShowAtoms) {
183 for(size_t i = 0; i < nAtoms; ++i) {
184 double X = coords[i][0];
185 double Y = coords[i][1];
186 vtkNew<vtkUnstructuredGrid> vtu{};
187 DiagramToVTU(vtu, atoms[i], dummy, *this, 3, false);
188 TranslateDiagram(vtu, std::array<double, 3>{X, Y, 0.0});
189 output->SetBlock(i, vtu);
190 }
191 }
192
193 } else if(nAtoms == 3) {
194
195 if(ShowAtoms) {
196 for(size_t i = 0; i < nAtoms; ++i) {
197 double X = coords[i][0];
198 double Y = coords[i][1];
199 vtkNew<vtkUnstructuredGrid> vtu{};
200 DiagramToVTU(vtu, atoms[i], dummy, *this, 3, false);
201 TranslateDiagram(vtu, std::array<double, 3>{X, Y, 0.0});
202 output->SetBlock(i, vtu);
203 }
204 }
205
206 } else {
207
208 if(ShowAtoms) {
209 for(size_t i = 0; i < nAtoms; ++i) {
210 const auto angle
211 = 2.0 * M_PI * static_cast<double>(i) / static_cast<double>(nAtoms);
212 double X = spacing * maxPersistence * std::cos(angle);
213 double Y = spacing * maxPersistence * std::sin(angle);
214 vtkNew<vtkUnstructuredGrid> vtu{};
215 DiagramToVTU(vtu, atoms[i], dummy, *this, 3, false);
216 TranslateDiagram(vtu, std::array<double, 3>{X, Y, 0.0});
217 output->SetBlock(i, vtu);
218 }
219 }
220 }
221
222 int numDiags = diags.size();
223
224 for(int i = 0; i < numDiags; ++i) {
225 vtkNew<vtkUnstructuredGrid> vtu{};
226 if(!ComputePoints) {
227 DiagramToVTU(vtu, diags[i], dummy, *this, 3, false);
228 }
229
230 double X = 0;
231 double Y = 0;
232 for(size_t iAtom = 0; iAtom < nAtoms; ++iAtom) {
233 X += weights[i][iAtom] * coords[iAtom][0];
234 Y += weights[i][iAtom] * coords[iAtom][1];
235 }
236
237 TranslateDiagram(vtu, std::array<double, 3>{X, Y, 0.0});
238 output->SetBlock(i + n_existing_blocks, vtu);
239 }
240
241 for(size_t i = 0; i < 3; ++i) {
242 vtkNew<vtkDoubleArray> col{};
243 col->SetNumberOfValues(nDiags);
244 std::string name;
245
246 if(i == 0) {
247 name = "X";
248 } else if(i == 1) {
249 name = "Y";
250 } else {
251 name = "Z";
252 }
253 col->SetName(name.c_str());
254 for(size_t j = 0; j < nDiags; ++j) {
255 if(i == 0) {
256 col->SetValue(j, xVector[j]);
257 } else if(i == 1) {
258 col->SetValue(j, yVector[j]);
259 } else {
260 col->SetValue(j, zVector[j]);
261 }
262 }
263 col->Modified();
264 outputCoordinates->AddColumn(col);
265 }
266
267 const auto zeroPad
268 = [](std::string &colName, const size_t numberCols, const size_t colIdx) {
269 std::string max{std::to_string(numberCols - 1)};
270 std::string cur{std::to_string(colIdx)};
271 std::string zer(max.size() - cur.size(), '0');
272 colName.append(zer).append(cur);
273 };
274
275 vtkNew<vtkTable> temp;
276 temp->DeepCopy(weightsVTK);
277 for(int i = 0; i < temp->GetNumberOfColumns(); ++i) {
278 int test = 0;
279 const auto array = temp->GetColumn(i);
280
281 for(size_t j = 0; j < nDiags; ++j) {
282 std::string name{"Atom"};
283 zeroPad(name, nDiags, j);
284 if(strcmp(name.c_str(), temp->GetColumnName(i)) == 0) {
285 test += 1;
286 }
287 }
288 if(test > 0) {
289 continue;
290 }
291 outputCoordinates->AddColumn(array);
292 }
293
294 for(size_t i = 0; i < nAtoms; ++i) {
295 vtkNew<vtkVariantArray> row{};
296 row->SetNumberOfValues(outputCoordinates->GetNumberOfColumns());
297 for(int j = 0; j < outputCoordinates->GetNumberOfColumns(); ++j) {
298 if(strcmp(outputCoordinates->GetColumnName(j), "X") == 0) {
299 row->SetValue(j, trueCoords[i][0]);
300 } else if(strcmp(outputCoordinates->GetColumnName(j), "Y") == 0) {
301 row->SetValue(j, trueCoords[i][1]);
302 } else if(strcmp(outputCoordinates->GetColumnName(j), "Z") == 0) {
303 row->SetValue(j, trueCoords[i][2]);
304 } else if(strcmp(outputCoordinates->GetColumnName(j), "ClusterID") == 0) {
305 row->SetValue(j, -1);
306 } else {
307 continue;
308 }
309 }
310 row->Modified();
311 outputCoordinates->InsertNextRow(row);
312 }
313}
#define M_PI
Definition Os.h:50
TTK processing package for the computation of a Dictionary of Persistence Diagrams and barycentric we...
int FillOutputPortInformation(int port, vtkInformation *info) override
int FillInputPortInformation(int port, vtkInformation *info) override
void GetOutputDiagrams(vtkMultiBlockDataSet *output, vtkTable *output_coordinates, const std::vector< ttk::DiagramType > &diags, std::vector< ttk::DiagramType > &atoms, vtkTable *weights_vtk, const std::vector< std::vector< double > > &weights, const double spacing, const double maxPersistence) const
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
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
void computeAtomsCoordinates(std::vector< ttk::DiagramType > &atoms, const std::vector< std::vector< double > > &vectorWeights, std::vector< std::array< double, 3 > > &coords, std::vector< std::array< double, 3 > > &trueCoords, std::vector< double > &xVector, std::vector< double > &yVector, std::vector< double > &zVector, const double spacing, const size_t nAtoms) const
void execute(std::vector< DiagramType > &dictDiagrams, std::vector< std::vector< double > > &vectorWeights, std::vector< DiagramType > &Barycenters) const
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
vtkStandardNewMacro(ttkPersistenceDiagramDictionaryDecoding)
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...