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.");
147 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> origins, originsPrime;
149 origins, vtkMultiBlockDataSet::SafeDownCast((blockBary->GetBlock(0))));
151 originsPrime, vtkMultiBlockDataSet::SafeDownCast(blockBary->GetBlock(1)));
153 std::vector<ttk::ftm::MergeTree<float>> originsTrees, originsPrimeTrees;
154 std::vector<vtkUnstructuredGrid *> originsTreeNodes, originsTreeArcs,
155 originsPrimeTreeNodes, originsPrimeTreeArcs;
156 std::vector<vtkDataSet *> originsTreeSegmentations,
157 originsPrimeTreeSegmentations;
161 origins, originsTrees, originsTreeNodes, originsTreeArcs,
162 originsTreeSegmentations, useSadMaxPairs);
163 ttk::ftm::constructTrees<float>(originsPrime, originsPrimeTrees,
164 originsTreeNodes, originsTreeArcs,
165 originsTreeSegmentations, useSadMaxPairs);
173 auto vS = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(0));
175 std::vector<unsigned int> allNoAxes(
noLayers_);
176 for(
unsigned int l = 0; l <
noLayers_; ++l) {
177 auto layerVectorsTable = vtkTable::SafeDownCast(vS->GetBlock(l));
178 unsigned int maxBoundNoAxes = 1;
179 while(not layerVectorsTable->GetColumnByName(
181 maxBoundNoAxes *= 10;
182 unsigned int noAxes = 1;
183 while(layerVectorsTable->GetColumnByName(
187 allNoAxes[l] = noAxes;
194 = vtkTable::SafeDownCast(coefficients->GetBlock(0))->GetNumberOfRows();
195 auto noCoefs = coefficients->GetNumberOfBlocks();
197 allAlphas_.resize(numberOfInputs, std::vector<torch::Tensor>(noCoefs));
198#ifdef TTK_ENABLE_OPENMP
199#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
201 for(
unsigned int l = 0; l < noCoefs; ++l) {
202 auto layerCoefficientsTable
203 = vtkTable::SafeDownCast(coefficients->GetBlock(l));
204 auto noAxes = (customRec ? allNoAxes[getLatentLayerIndex()] : allNoAxes[l]);
205 std::vector<std::vector<float>> alphas(
206 numberOfInputs, std::vector<float>(noAxes));
207 for(
unsigned int g = 0; g < noAxes; ++g) {
208 auto array = layerCoefficientsTable->GetColumnByName(
210 for(
unsigned int i = 0; i < numberOfInputs; ++i)
211 alphas[i][g] = array->GetVariantValue(i).ToFloat();
213 for(
unsigned int i = 0; i < numberOfInputs; ++i)
214 allAlphas_[i][l] = torch::tensor(alphas[i]).reshape({-1, 1});
222 auto vSPrime = vtkMultiBlockDataSet::SafeDownCast(vectors->GetBlock(1));
223 std::vector<unsigned int *> allRevNodeCorr(
noLayers_),
225 std::vector<unsigned int> allRevNodeCorrSize(
noLayers_),
227#ifdef TTK_ENABLE_OPENMP
228#pragma omp parallel for schedule(dynamic) num_threads(this->threadNumber_)
230 for(
unsigned int l = 0; l < vSTensor_.size(); ++l) {
231 auto layerVectorsTable = vtkTable::SafeDownCast(vS->GetBlock(l));
232 auto layerVectorsPrimeTable = vtkTable::SafeDownCast(vSPrime->GetBlock(l));
233 auto noRows = layerVectorsTable->GetNumberOfRows();
234 auto noRows2 = layerVectorsPrimeTable->GetNumberOfRows();
235 std::vector<float> vSTensor(noRows * allNoAxes[l]),
236 vSPrimeTensor(noRows2 * allNoAxes[l]);
237 for(
unsigned int v = 0; v < allNoAxes[l]; ++v) {
240 for(
unsigned int i = 0; i < noRows; ++i)
241 vSTensor[i * allNoAxes[l] + v]
242 = layerVectorsTable->GetColumnByName(name.c_str())
245 for(
unsigned int i = 0; i < noRows2; ++i)
246 vSPrimeTensor[i * allNoAxes[l] + v]
247 = layerVectorsPrimeTable->GetColumnByName(name.c_str())
251 vSTensor_[l] = torch::tensor(vSTensor).reshape({noRows, allNoAxes[l]});
253 = torch::tensor(vSPrimeTensor).reshape({noRows2, allNoAxes[l]});
255 = ttkUtils::GetPointer<unsigned int>(vtkDataArray::SafeDownCast(
256 layerVectorsTable->GetColumnByName(
"revNodeCorr")));
257 allRevNodeCorrSize[l] = noRows;
258 allRevNodeCorrPrime[l]
259 = ttkUtils::GetPointer<unsigned int>(vtkDataArray::SafeDownCast(
260 layerVectorsPrimeTable->GetColumnByName(
"revNodeCorr")));
261 allRevNodeCorrPrimeSize[l] = noRows2;
267 execute(originsTrees, originsPrimeTrees, allRevNodeCorr, allRevNodeCorrPrime,
268 allRevNodeCorrSize, allRevNodeCorrPrimeSize);
273 auto output_data = vtkMultiBlockDataSet::GetData(outputVector, 0);
278 auto originsMatchingSize = getLatentLayerIndex() + 1;
279 std::vector<std::vector<ttk::ftm::idNode>> originsMatchingVectorT(
280 originsMatchingSize),
281 invOriginsMatchingVectorT = originsMatchingVectorT;
282 for(
unsigned int l = 0; l < originsMatchingVectorT.size(); ++l) {
283 auto array = vtkTable::SafeDownCast(
284 (l == 0 ? vS : vSPrime)->GetBlock((l == 0 ? l : l - 1)))
285 ->GetColumnByName(
"nextOriginMatching");
286 originsMatchingVectorT[l].clear();
287 originsMatchingVectorT[l].resize(array->GetNumberOfTuples());
288 for(
unsigned int i = 0; i < originsMatchingVectorT[l].size(); ++i)
289 originsMatchingVectorT[l][i] = array->GetVariantValue(i).ToUnsignedInt();
290 reverseMatchingVector<float>(originsPrime_[l].mTree,
291 originsMatchingVectorT[l],
292 invOriginsMatchingVectorT[l]);
294 auto dataMatchingSize = getLatentLayerIndex() + 2;
295 std::vector<std::vector<std::vector<ttk::ftm::idNode>>> dataMatchingVectorT(
297 invDataMatchingVectorT = dataMatchingVectorT;
298 std::vector<std::vector<ttk::ftm::idNode>> invReconstMatchingVectorT(
301 for(
unsigned int l = 0; l < dataMatchingVectorT.size(); ++l) {
302 dataMatchingVectorT[l].resize(numberOfInputs);
303 invDataMatchingVectorT[l].resize(numberOfInputs);
304 for(
unsigned int i = 0; i < dataMatchingVectorT[l].size(); ++i) {
305 std::stringstream ss;
308 auto array = vtkTable::SafeDownCast(
309 (l == 0 ? vS : vSPrime)->GetBlock((l == 0 ? l : l - 1)))
310 ->GetColumnByName(ss.str().c_str());
311 dataMatchingVectorT[l][i].clear();
312 dataMatchingVectorT[l][i].resize(array->GetNumberOfTuples());
313 for(
unsigned int j = 0; j < dataMatchingVectorT[l][i].size(); ++j)
314 dataMatchingVectorT[l][i][j]
315 = array->GetVariantValue(j).ToUnsignedInt();
317 = (l == 0 ? vtkTable::SafeDownCast(coefficients->GetBlock(0))
318 ->GetColumnByName(
"treeNoNodes")
321 : recs_[i][l - 1].mTree.tree.getNumberOfNodes());
323 noNodes, dataMatchingVectorT[l][i], invDataMatchingVectorT[l][i]);
326 for(
unsigned int i = 0; i < invReconstMatchingVectorT.size(); ++i) {
327 std::stringstream ss;
328 ss <<
"reconstMatching"
330 auto array = vtkTable::SafeDownCast(vSPrime->GetBlock(
noLayers_ - 1))
331 ->GetColumnByName(ss.str().c_str());
332 invReconstMatchingVectorT[i].resize(array->GetNumberOfTuples());
333 for(
unsigned int j = 0; j < invReconstMatchingVectorT[i].size(); ++j)
334 invReconstMatchingVectorT[i][j]
335 = array->GetVariantValue(j).ToUnsignedInt();
342 std::vector<std::vector<ttk::ftm::idNode>> originsMatchingVector;
343 std::vector<std::vector<double>> originsPersPercent, originsPersDiff;
344 std::vector<double> originPersPercent, originPersDiff;
345 std::vector<int> originPersistenceOrder;
346 ttk::wae::computeTrackingInformation(
347 origins_, originsPrime_, originsMatchingVectorT, invOriginsMatchingVectorT,
349 originsPersDiff, originPersPercent, originPersDiff, originPersistenceOrder);
355 output_data->SetNumberOfBlocks(1);
358 data->SetNumberOfBlocks(recs_[0].size());
361 dataSeg->SetNumberOfBlocks(recs_.size());
362 for(
unsigned int l = 0; l < recs_[0].size(); ++l) {
365 out_layer_i->SetNumberOfBlocks(recs_.size());
366 std::vector<ttk::ftm::MergeTree<float> *> trees(recs_.size());
367 for(
unsigned int i = 0; i < recs_.size(); ++i)
368 trees[i] = &(recs_[i][l].mTree);
371 std::vector<std::vector<std::tuple<std::string, std::vector<int>>>>
372 customIntArrays(recs_.size());
373 std::vector<std::vector<std::tuple<std::string, std::vector<double>>>>
374 customDoubleArrays(recs_.size());
375 unsigned int lShift = 1;
376 ttk::wae::computeCustomArrays(
378 invReconstMatchingVectorT, originsMatchingVector,
379 originsMatchingVectorT, originsPersPercent, originsPersDiff,
380 originPersistenceOrder, l, lShift, customIntArrays, customDoubleArrays);
383 ttk::wae::makeManyOutput(trees, out_layer_i, customIntArrays,
387 data->SetBlock(l, out_layer_i);
388 std::stringstream ss;
390 data->GetMetaData(l)->Set(vtkCompositeDataSet::NAME(), ss.str());
392 output_data->SetBlock(0, data);
393 unsigned int num = 0;
394 std::stringstream ss;
396 output_data->GetMetaData(num)->Set(vtkCompositeDataSet::NAME(), ss.str());
399 if(!customRecs_.empty()) {
400 std::vector<std::vector<std::tuple<std::string, std::vector<int>>>>
401 customRecsIntArrays(customRecs_.size());
402 std::vector<std::vector<std::tuple<std::string, std::vector<double>>>>
403 customRecsDoubleArrays(customRecs_.size());
404 std::vector<ttk::ftm::MergeTree<float> *> trees(customRecs_.size());
405 for(
unsigned int i = 0; i < customRecs_.size(); ++i)
406 trees[i] = &(customRecs_[i].mTree);
407 std::vector<std::vector<int>> customOriginPersOrder(customRecs_.size());
408 for(
unsigned int i = 0; i < customRecs_.size(); ++i) {
409 trees[i] = &(customRecs_[i].mTree);
410 std::vector<ttk::ftm::idNode> matchingVector;
413 customOriginPersOrder[i].resize(
414 customRecs_[i].mTree.tree.getNumberOfNodes());
415 for(
unsigned int j = 0; j < matchingVector.size(); ++j) {
416 if(matchingVector[j] < originPersistenceOrder.size())
417 customOriginPersOrder[i][j]
418 = originPersistenceOrder[matchingVector[j]];
420 customOriginPersOrder[i][j] = -1;
422 std::string name4{
"OriginPersOrder"};
423 customRecsIntArrays[i].emplace_back(
424 std::make_tuple(name4, customOriginPersOrder[i]));
428 ttk::wae::makeManyOutput(trees, dataCustom, customRecsIntArrays,
432 output_data->SetBlock(0, dataCustom);