96 vtkInformationVector **inputVector,
97 vtkInformationVector *outputVector) {
98#ifndef TTK_ENABLE_TORCH
101 printErr(
"This filter requires Torch.");
107 auto blockBary = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
108 auto vectors = vtkMultiBlockDataSet::GetData(inputVector[1], 0);
109 auto coefficients = vtkMultiBlockDataSet::GetData(inputVector[2], 0);
112 printMsg(
"Load parameters from field data.");
113 std::vector<std::string> 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());
123 double const value = array->GetTuple1(0);
124 if(paramName ==
"activate")
126 else if(paramName ==
"activationFunction")
131 printMsg(
" - " + paramName +
" was not found in the field data.");
132 auto stringValue = std::to_string(
134 : (paramName ==
"activationFunction"
137 printMsg(
" - " + paramName +
" = " + stringValue);
140 printMsg(
"Computation with normalized Wasserstein.");
142 printMsg(
"Computation without normalized Wasserstein.");
144 auto diagramPairTypesArray = fd->GetArray(
"DiagramPairTypes");
145 if(diagramPairTypesArray)
146 DiagramPairTypes = diagramPairTypesArray->GetTuple1(0);
151 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> origins, originsPrime;
153 origins, vtkMultiBlockDataSet::SafeDownCast((blockBary->GetBlock(0))));
155 originsPrime, vtkMultiBlockDataSet::SafeDownCast(blockBary->GetBlock(1)));
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;
165 origins, originsTrees, originsTreeNodes, originsTreeArcs,
166 originsTreeSegmentations, useSecondPairsType, DiagramPairTypes);
168 originsPrime, originsPrimeTrees, originsTreeNodes, originsTreeArcs,
169 originsTreeSegmentations, useSecondPairsType, DiagramPairTypes);
177 auto vS = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(0));
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(
185 maxBoundNoAxes *= 10;
186 unsigned int noAxes = 1;
187 while(layerVectorsTable->GetColumnByName(
191 allNoAxes[l] = noAxes;
198 = vtkTable::SafeDownCast(coefficients->GetBlock(0))->GetNumberOfRows();
199 auto noCoefs = coefficients->GetNumberOfBlocks();
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_)
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(
214 for(
unsigned int i = 0; i < numberOfInputs; ++i)
215 alphas[i][g] = array->GetVariantValue(i).ToFloat();
217 for(
unsigned int i = 0; i < numberOfInputs; ++i)
218 allAlphas_[i][l] = torch::tensor(alphas[i]).reshape({-1, 1});
226 auto vSPrime = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(1));
227 std::vector<unsigned int *> allRevNodeCorr(
noLayers_),
229 std::vector<unsigned int> allRevNodeCorrSize(
noLayers_),
231#ifdef TTK_ENABLE_OPENMP
232#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
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) {
244 for(
unsigned int i = 0; i < noRows; ++i)
245 vSTensor[i * allNoAxes[l] + v]
246 = layerVectorsTable->GetColumnByName(name.c_str())
249 for(
unsigned int i = 0; i < noRows2; ++i)
250 vSPrimeTensor[i * allNoAxes[l] + v]
251 = layerVectorsPrimeTable->GetColumnByName(name.c_str())
255 vSTensorCopy_[l] = torch::tensor(vSTensor).reshape({noRows, allNoAxes[l]});
256 vSPrimeTensorCopy_[l]
257 = torch::tensor(vSPrimeTensor).reshape({noRows2, allNoAxes[l]});
260 layerVectorsTable->GetColumnByName(
"revNodeCorr")));
261 allRevNodeCorrSize[l] = noRows;
262 allRevNodeCorrPrime[l]
264 layerVectorsPrimeTable->GetColumnByName(
"revNodeCorr")));
265 allRevNodeCorrPrimeSize[l] = noRows2;
271 execute(originsTrees, originsPrimeTrees, allRevNodeCorr, allRevNodeCorrPrime,
272 allRevNodeCorrSize, allRevNodeCorrPrimeSize);
277 auto output_data = vtkMultiBlockDataSet::GetData(outputVector, 0);
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();
295 originsMatchingVectorT[l],
296 invOriginsMatchingVectorT[l]);
298 auto dataMatchingSize = getLatentLayerIndex() + 2;
299 std::vector<std::vector<std::vector<ttk::ftm::idNode>>> dataMatchingVectorT(
301 invDataMatchingVectorT = dataMatchingVectorT;
302 std::vector<std::vector<ttk::ftm::idNode>> invReconstMatchingVectorT(
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;
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();
321 = (l == 0 ? vtkTable::SafeDownCast(coefficients->GetBlock(0))
322 ->GetColumnByName(
"treeNoNodes")
325 : recs_[i][l - 1].mTree.tree.getNumberOfNodes());
327 noNodes, dataMatchingVectorT[l][i], invDataMatchingVectorT[l][i]);
330 for(
unsigned int i = 0; i < invReconstMatchingVectorT.size(); ++i) {
331 std::stringstream ss;
332 ss <<
"reconstMatching"
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();
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,
353 originsPersPercent, originsPersDiff, originPersPercent, originPersDiff,
354 originPersistenceOrder);
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);
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(
383 invReconstMatchingVectorT, originsMatchingVector,
384 originsMatchingVectorT, originsPersPercent, originsPersDiff,
385 originPersistenceOrder, l, lShift, customIntArrays, customDoubleArrays);
388 ttk::wnn::makeManyOutput(trees, out_layer_i, customIntArrays,
392 data->SetBlock(l, out_layer_i);
393 std::stringstream ss;
395 data->GetMetaData(l)->Set(vtkCompositeDataSet::NAME(), ss.str());
397 output_data->SetBlock(0, data);
398 unsigned int num = 0;
399 std::stringstream ss;
401 output_data->GetMetaData(num)->Set(vtkCompositeDataSet::NAME(), ss.str());
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;
417 customRecs_[i].mTree,
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]];
426 customOriginPersOrder[i][j] = -1;
428 std::string name4{
"OriginPersOrder"};
429 customRecsIntArrays[i].emplace_back(
430 std::make_tuple(name4, customOriginPersOrder[i]));
434 ttk::wnn::makeManyOutput(trees, dataCustom, customRecsIntArrays,
438 output_data->SetBlock(0, dataCustom);