TTK
Loading...
Searching...
No Matches
ttkMergeTreeAutoencoderDecoding.cpp
Go to the documentation of this file.
5#include <ttkMergeTreeUtils.h>
6
7#include <vtkInformation.h>
8
9#include <vtkDataArray.h>
10#include <vtkDataSet.h>
11#include <vtkMultiBlockDataSet.h>
12#include <vtkObjectFactory.h>
13#include <vtkPointData.h>
14#include <vtkSmartPointer.h>
15#include <vtkTable.h>
16
17#include <ttkMacros.h>
18#include <ttkUtils.h>
19
20// A VTK macro that enables the instantiation of this class via ::New()
21// You do not have to modify this
23
37 this->SetNumberOfInputPorts(3);
38 this->SetNumberOfOutputPorts(1);
39}
40
49 int port, vtkInformation *info) {
50 if(port == 0 or port == 1 or port == 2) {
51 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
52 return 1;
53 }
54 return 0;
55}
56
73 int port, vtkInformation *info) {
74 if(port == 0) {
76 return 1;
77 }
78 return 0;
79}
80
95 vtkInformation *ttkNotUsed(request),
96 vtkInformationVector **inputVector,
97 vtkInformationVector *outputVector) {
98#ifndef TTK_ENABLE_TORCH
99 TTK_FORCE_USE(inputVector);
100 TTK_FORCE_USE(outputVector);
101 printErr("This filter requires Torch.");
102 return 0;
103#else
104 // --------------------------------------------------------------------------
105 // --- Read Input
106 // --------------------------------------------------------------------------
107 auto blockBary = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
108 auto vectors = vtkMultiBlockDataSet::GetData(inputVector[1], 0);
109 auto coefficients = vtkMultiBlockDataSet::GetData(inputVector[2], 0);
110
111 // Parameters
112 printMsg("Load parameters from field data.");
113 std::vector<std::string> paramNames;
114 getParamNames(paramNames);
115 paramNames.emplace_back("activate");
116 paramNames.emplace_back("activationFunction");
117 auto fd = coefficients->GetFieldData();
118 if(not fd->GetArray("activate"))
119 fd = coefficients->GetBlock(0)->GetFieldData();
120 for(auto paramName : paramNames) {
121 auto array = fd->GetArray(paramName.c_str());
122 if(array) {
123 double const value = array->GetTuple1(0);
124 if(paramName == "activate")
125 activate_ = value;
126 else if(paramName == "activationFunction")
127 activationFunction_ = value;
128 else
129 setParamValueFromName(paramName, value);
130 } else
131 printMsg(" - " + paramName + " was not found in the field data.");
132 auto stringValue = std::to_string(
133 (paramName == "activate" ? activate_
134 : (paramName == "activationFunction"
136 : getParamValueFromName(paramName))));
137 printMsg(" - " + paramName + " = " + stringValue);
138 }
140 printMsg("Computation with normalized Wasserstein.");
141 else
142 printMsg("Computation without normalized Wasserstein.");
143
144 auto diagramPairTypesArray = fd->GetArray("DiagramPairTypes");
145 if(diagramPairTypesArray)
146 DiagramPairTypes = diagramPairTypesArray->GetTuple1(0);
147
148 // -----------------
149 // Origins
150 // -----------------
151 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> origins, originsPrime;
153 origins, vtkMultiBlockDataSet::SafeDownCast((blockBary->GetBlock(0))));
155 originsPrime, vtkMultiBlockDataSet::SafeDownCast(blockBary->GetBlock(1)));
156
157 std::vector<ttk::ftm::MergeTree<float>> originsTrees, originsPrimeTrees;
158 std::vector<vtkUnstructuredGrid *> originsTreeNodes, originsTreeArcs,
159 originsPrimeTreeNodes, originsPrimeTreeArcs;
160 std::vector<vtkDataSet *> originsTreeSegmentations,
161 originsPrimeTreeSegmentations;
162
163 bool useSecondPairsType = (mixtureCoefficient_ == 0);
165 origins, originsTrees, originsTreeNodes, originsTreeArcs,
166 originsTreeSegmentations, useSecondPairsType, DiagramPairTypes);
168 originsPrime, originsPrimeTrees, originsTreeNodes, originsTreeArcs,
169 originsTreeSegmentations, useSecondPairsType, DiagramPairTypes);
170 // If merge trees are provided in input and normalization is not asked
173
174 // -----------------
175 // Number of axes per layer
176 // -----------------
177 auto vS = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(0));
178 noLayers_ = vS->GetNumberOfBlocks();
179 std::vector<unsigned int> allNoAxes(noLayers_);
180 for(unsigned int l = 0; l < noLayers_; ++l) {
181 auto layerVectorsTable = vtkTable::SafeDownCast(vS->GetBlock(l));
182 unsigned int maxBoundNoAxes = 1;
183 while(not layerVectorsTable->GetColumnByName(
184 ttk::axa::getTableVectorName(maxBoundNoAxes, 0, 0, 0, false).c_str()))
185 maxBoundNoAxes *= 10;
186 unsigned int noAxes = 1;
187 while(layerVectorsTable->GetColumnByName(
188 ttk::axa::getTableVectorName(maxBoundNoAxes, noAxes, 0, 0, false)
189 .c_str()))
190 noAxes += 1;
191 allNoAxes[l] = noAxes;
192 }
193
194 // -----------------
195 // Coefficients
196 // -----------------
197 auto numberOfInputs
198 = vtkTable::SafeDownCast(coefficients->GetBlock(0))->GetNumberOfRows();
199 auto noCoefs = coefficients->GetNumberOfBlocks();
200 bool customRec = (noCoefs != noLayers_);
201 allAlphas_.resize(numberOfInputs, std::vector<torch::Tensor>(noCoefs));
202#ifdef TTK_ENABLE_OPENMP
203#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
204#endif
205 for(unsigned int l = 0; l < noCoefs; ++l) {
206 auto layerCoefficientsTable
207 = vtkTable::SafeDownCast(coefficients->GetBlock(l));
208 auto noAxes = (customRec ? allNoAxes[getLatentLayerIndex()] : allNoAxes[l]);
209 std::vector<std::vector<float>> alphas(
210 numberOfInputs, std::vector<float>(noAxes));
211 for(unsigned int g = 0; g < noAxes; ++g) {
212 auto array = layerCoefficientsTable->GetColumnByName(
213 ttk::axa::getTableCoefficientName(noAxes, g).c_str());
214 for(unsigned int i = 0; i < numberOfInputs; ++i)
215 alphas[i][g] = array->GetVariantValue(i).ToFloat();
216 }
217 for(unsigned int i = 0; i < numberOfInputs; ++i)
218 allAlphas_[i][l] = torch::tensor(alphas[i]).reshape({-1, 1});
219 }
220
221 // -----------------
222 // Vectors
223 // -----------------
224 vSTensorCopy_.resize(noLayers_);
225 vSPrimeTensorCopy_.resize(noLayers_);
226 auto vSPrime = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(1));
227 std::vector<unsigned int *> allRevNodeCorr(noLayers_),
228 allRevNodeCorrPrime(noLayers_);
229 std::vector<unsigned int> allRevNodeCorrSize(noLayers_),
230 allRevNodeCorrPrimeSize(noLayers_);
231#ifdef TTK_ENABLE_OPENMP
232#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
233#endif
234 for(unsigned int l = 0; l < vSTensorCopy_.size(); ++l) {
235 auto layerVectorsTable = vtkTable::SafeDownCast(vS->GetBlock(l));
236 auto layerVectorsPrimeTable = vtkTable::SafeDownCast(vSPrime->GetBlock(l));
237 auto noRows = layerVectorsTable->GetNumberOfRows();
238 auto noRows2 = layerVectorsPrimeTable->GetNumberOfRows();
239 std::vector<float> vSTensor(noRows * allNoAxes[l]),
240 vSPrimeTensor(noRows2 * allNoAxes[l]);
241 for(unsigned int v = 0; v < allNoAxes[l]; ++v) {
242 std::string name
243 = ttk::axa::getTableVectorName(allNoAxes[l], v, 0, 0, false);
244 for(unsigned int i = 0; i < noRows; ++i)
245 vSTensor[i * allNoAxes[l] + v]
246 = layerVectorsTable->GetColumnByName(name.c_str())
247 ->GetVariantValue(i)
248 .ToFloat();
249 for(unsigned int i = 0; i < noRows2; ++i)
250 vSPrimeTensor[i * allNoAxes[l] + v]
251 = layerVectorsPrimeTable->GetColumnByName(name.c_str())
252 ->GetVariantValue(i)
253 .ToFloat();
254 }
255 vSTensorCopy_[l] = torch::tensor(vSTensor).reshape({noRows, allNoAxes[l]});
256 vSPrimeTensorCopy_[l]
257 = torch::tensor(vSPrimeTensor).reshape({noRows2, allNoAxes[l]});
258 allRevNodeCorr[l]
259 = ttkUtils::GetPointer<unsigned int>(vtkDataArray::SafeDownCast(
260 layerVectorsTable->GetColumnByName("revNodeCorr")));
261 allRevNodeCorrSize[l] = noRows;
262 allRevNodeCorrPrime[l]
263 = ttkUtils::GetPointer<unsigned int>(vtkDataArray::SafeDownCast(
264 layerVectorsPrimeTable->GetColumnByName("revNodeCorr")));
265 allRevNodeCorrPrimeSize[l] = noRows2;
266 }
267
268 // -----------------
269 // Call base
270 // -----------------
271 execute(originsTrees, originsPrimeTrees, allRevNodeCorr, allRevNodeCorrPrime,
272 allRevNodeCorrSize, allRevNodeCorrPrimeSize);
273
274 // --------------------------------------------------------------------------
275 // --- Create Output
276 // --------------------------------------------------------------------------
277 auto output_data = vtkMultiBlockDataSet::GetData(outputVector, 0);
278
279 // ------------------------------------------
280 // --- Read Matchings
281 // ------------------------------------------
282 auto originsMatchingSize = getLatentLayerIndex() + 1;
283 std::vector<std::vector<ttk::ftm::idNode>> originsMatchingVectorT(
284 originsMatchingSize),
285 invOriginsMatchingVectorT = originsMatchingVectorT;
286 for(unsigned int l = 0; l < originsMatchingVectorT.size(); ++l) {
287 auto array = vtkTable::SafeDownCast(
288 (l == 0 ? vS : vSPrime)->GetBlock((l == 0 ? l : l - 1)))
289 ->GetColumnByName("nextOriginMatching");
290 originsMatchingVectorT[l].clear();
291 originsMatchingVectorT[l].resize(array->GetNumberOfTuples());
292 for(unsigned int i = 0; i < originsMatchingVectorT[l].size(); ++i)
293 originsMatchingVectorT[l][i] = array->GetVariantValue(i).ToUnsignedInt();
294 ttk::axa::reverseMatchingVector<float>(originsPrimeCopy_[l].mTree,
295 originsMatchingVectorT[l],
296 invOriginsMatchingVectorT[l]);
297 }
298 auto dataMatchingSize = getLatentLayerIndex() + 2;
299 std::vector<std::vector<std::vector<ttk::ftm::idNode>>> dataMatchingVectorT(
300 dataMatchingSize),
301 invDataMatchingVectorT = dataMatchingVectorT;
302 std::vector<std::vector<ttk::ftm::idNode>> invReconstMatchingVectorT(
303 numberOfInputs);
304 if(not customRec) {
305 for(unsigned int l = 0; l < dataMatchingVectorT.size(); ++l) {
306 dataMatchingVectorT[l].resize(numberOfInputs);
307 invDataMatchingVectorT[l].resize(numberOfInputs);
308 for(unsigned int i = 0; i < dataMatchingVectorT[l].size(); ++i) {
309 std::stringstream ss;
310 ss << "matching"
311 << ttk::axa::getTableTreeName(dataMatchingVectorT[l].size(), i);
312 auto array = vtkTable::SafeDownCast(
313 (l == 0 ? vS : vSPrime)->GetBlock((l == 0 ? l : l - 1)))
314 ->GetColumnByName(ss.str().c_str());
315 dataMatchingVectorT[l][i].clear();
316 dataMatchingVectorT[l][i].resize(array->GetNumberOfTuples());
317 for(unsigned int j = 0; j < dataMatchingVectorT[l][i].size(); ++j)
318 dataMatchingVectorT[l][i][j]
319 = array->GetVariantValue(j).ToUnsignedInt();
320 auto noNodes
321 = (l == 0 ? vtkTable::SafeDownCast(coefficients->GetBlock(0))
322 ->GetColumnByName("treeNoNodes")
323 ->GetVariantValue(i)
324 .ToUnsignedInt()
325 : recs_[i][l - 1].mTree.tree.getNumberOfNodes());
327 noNodes, dataMatchingVectorT[l][i], invDataMatchingVectorT[l][i]);
328 }
329 }
330 for(unsigned int i = 0; i < invReconstMatchingVectorT.size(); ++i) {
331 std::stringstream ss;
332 ss << "reconstMatching"
333 << ttk::axa::getTableTreeName(invReconstMatchingVectorT.size(), i);
334 auto array = vtkTable::SafeDownCast(vSPrime->GetBlock(noLayers_ - 1))
335 ->GetColumnByName(ss.str().c_str());
336 invReconstMatchingVectorT[i].resize(array->GetNumberOfTuples());
337 for(unsigned int j = 0; j < invReconstMatchingVectorT[i].size(); ++j)
338 invReconstMatchingVectorT[i][j]
339 = array->GetVariantValue(j).ToUnsignedInt();
340 }
341 }
342
343 // ------------------------------------------
344 // --- Tracking information
345 // ------------------------------------------
346 std::vector<std::vector<ttk::ftm::idNode>> originsMatchingVector;
347 std::vector<std::vector<double>> originsPersPercent, originsPersDiff;
348 std::vector<double> originPersPercent, originPersDiff;
349 std::vector<int> originPersistenceOrder;
350 ttk::wnn::computeTrackingInformation(
351 originsCopy_, originsPrimeCopy_, originsMatchingVectorT,
352 invOriginsMatchingVectorT, isPersistenceDiagram_, originsMatchingVector,
353 originsPersPercent, originsPersDiff, originPersPercent, originPersDiff,
354 originPersistenceOrder);
355
356 // ------------------------------------------
357 // --- Data
358 // ------------------------------------------
359 if(!recs_.empty()) {
360 output_data->SetNumberOfBlocks(1);
363 data->SetNumberOfBlocks(recs_[0].size());
366 dataSeg->SetNumberOfBlocks(recs_.size());
367 for(unsigned int l = 0; l < recs_[0].size(); ++l) {
370 out_layer_i->SetNumberOfBlocks(recs_.size());
371 std::vector<ttk::ftm::MergeTree<float> *> trees(recs_.size());
372 for(unsigned int i = 0; i < recs_.size(); ++i)
373 trees[i] = &(recs_[i][l].mTree);
374
375 // Custom arrays
376 std::vector<std::vector<std::tuple<std::string, std::vector<int>>>>
377 customIntArrays(recs_.size());
378 std::vector<std::vector<std::tuple<std::string, std::vector<double>>>>
379 customDoubleArrays(recs_.size());
380 unsigned int lShift = 1;
381 ttk::wnn::computeCustomArrays(
382 recs_, persCorrelationMatrix_, invDataMatchingVectorT,
383 invReconstMatchingVectorT, originsMatchingVector,
384 originsMatchingVectorT, originsPersPercent, originsPersDiff,
385 originPersistenceOrder, l, lShift, customIntArrays, customDoubleArrays);
386
387 // Create output
388 ttk::wnn::makeManyOutput(trees, out_layer_i, customIntArrays,
389 customDoubleArrays, mixtureCoefficient_,
391 this->debugLevel_);
392 data->SetBlock(l, out_layer_i);
393 std::stringstream ss;
394 ss << "Layer" << l;
395 data->GetMetaData(l)->Set(vtkCompositeDataSet::NAME(), ss.str());
396 }
397 output_data->SetBlock(0, data);
398 unsigned int num = 0;
399 std::stringstream ss;
400 ss << "layers" << (isPersistenceDiagram_ ? "Diagrams" : "Trees");
401 output_data->GetMetaData(num)->Set(vtkCompositeDataSet::NAME(), ss.str());
402 }
403
404 if(!customRecs_.empty()) {
405 std::vector<std::vector<std::tuple<std::string, std::vector<int>>>>
406 customRecsIntArrays(customRecs_.size());
407 std::vector<std::vector<std::tuple<std::string, std::vector<double>>>>
408 customRecsDoubleArrays(customRecs_.size());
409 std::vector<ttk::ftm::MergeTree<float> *> trees(customRecs_.size());
410 for(unsigned int i = 0; i < customRecs_.size(); ++i)
411 trees[i] = &(customRecs_[i].mTree);
412 std::vector<std::vector<int>> customOriginPersOrder(customRecs_.size());
413 for(unsigned int i = 0; i < customRecs_.size(); ++i) {
414 trees[i] = &(customRecs_[i].mTree);
415 std::vector<ttk::ftm::idNode> matchingVector;
416 ttk::axa::getInverseMatchingVector(originsCopy_[0].mTree,
417 customRecs_[i].mTree,
418 customMatchings_[i], matchingVector);
419 customOriginPersOrder[i].resize(
420 customRecs_[i].mTree.tree.getNumberOfNodes());
421 for(unsigned int j = 0; j < matchingVector.size(); ++j) {
422 if(matchingVector[j] < originPersistenceOrder.size())
423 customOriginPersOrder[i][j]
424 = originPersistenceOrder[matchingVector[j]];
425 else
426 customOriginPersOrder[i][j] = -1;
427 }
428 std::string name4{"OriginPersOrder"};
429 customRecsIntArrays[i].emplace_back(
430 std::make_tuple(name4, customOriginPersOrder[i]));
431 }
434 ttk::wnn::makeManyOutput(trees, dataCustom, customRecsIntArrays,
435 customRecsDoubleArrays, mixtureCoefficient_,
437 this->debugLevel_);
438 output_data->SetBlock(0, dataCustom);
439 }
440
441 // return success
442 return 1;
443#endif
444}
#define TTK_FORCE_USE(x)
Force the compiler to use the function/method parameter.
Definition BaseClass.h:57
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
static vtkInformationIntegerKey * SAME_DATA_TYPE_AS_INPUT_PORT()
TTK VTK-filter that wraps the ttk::MergeTreeAutoencoderDecoding module.
int FillInputPortInformation(int port, vtkInformation *info) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
static DT * GetPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.h:59
int debugLevel_
Definition Debug.h:379
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
void execute(std::vector< ttk::ftm::MergeTree< float > > &originsTrees, std::vector< ttk::ftm::MergeTree< float > > &originsPrimeTrees, std::vector< unsigned int * > &allRevNodeCorr, std::vector< unsigned int * > &allRevNodeCorrPrime, std::vector< unsigned int > &allRevNodeCorrSize, std::vector< unsigned int > &allRevNodeCorrPrimeSize)
void setParamValueFromName(std::string &paramName, double value)
void getParamNames(std::vector< std::string > &paramNames)
double getParamValueFromName(std::string &paramName)
std::vector< std::vector< double > > persCorrelationMatrix_
std::vector< std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > > customMatchings_
void reverseMatchingVector(unsigned int noNodes, std::vector< ftm::idNode > &matchingVector, std::vector< ftm::idNode > &invMatchingVector)
std::string getTableVectorName(int noAxes, int axeNum, int vId, int vComp, bool isSecondInput)
std::string getTableTreeName(int noTrees, int treeNum)
void getInverseMatchingVector(const ftm::MergeTree< dataType > &barycenter, const ftm::MergeTree< dataType > &tree, std::vector< std::tuple< ftm::idNode, ftm::idNode, double > > &matchings, std::vector< ftm::idNode > &matchingVector)
std::string getTableCoefficientName(int noAxes, int axeNum)
bool constructTrees(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< MergeTree< dataType > > &intermediateTrees, std::vector< vtkUnstructuredGrid * > &treesNodes, std::vector< vtkUnstructuredGrid * > &treesArcs, std::vector< vtkDataSet * > &treesSegmentation, const std::vector< bool > &useSecondPairsTypeVec, int diagramPairTypes=0)
void loadBlocks(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, vtkMultiBlockDataSet *blocks)
vtkStandardNewMacro(ttkMergeTreeAutoencoderDecoding)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)