TTK
Loading...
Searching...
No Matches
ttkMergeTreeDistanceMatrix.cpp
Go to the documentation of this file.
2#include <ttkMergeTreeUtils.h>
3#include <ttkUtils.h>
4
5#include <vtkDataObject.h> // For port information
6#include <vtkObjectFactory.h> // for new macro
7
8#include <vtkDoubleArray.h>
9#include <vtkInformation.h>
10#include <vtkStringArray.h>
11#include <vtkTable.h>
12
13using namespace ttk;
14using namespace ftm;
15
16// A VTK macro that enables the instantiation of this class via ::New()
17// You do not have to modify this
19
33 this->SetNumberOfInputPorts(2);
34 this->SetNumberOfOutputPorts(1);
35}
36
38
47 vtkInformation *info) {
48 if(port == 0 || port == 1) {
49 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
50 if(port == 1)
51 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
52 } else
53 return 0;
54
55 return 1;
56}
57
74 int port, vtkInformation *info) {
75 if(port == 0)
76 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTable");
77 else
78 return 0;
79
80 return 1;
81}
82
96template <class dataType>
98 vtkInformationVector *outputVector,
99 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees,
100 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> &inputTrees2) {
101
102 // Construct trees
103 const int numInputs = inputTrees.size();
104 std::vector<MergeTree<dataType>> intermediateTrees, intermediateTrees2;
105 bool const useSecondPairsType
106 = (mixtureCoefficient_ == 0); // only for PD support
108 inputTrees, intermediateTrees, useSecondPairsType, DiagramPairTypes);
110 or (mixtureCoefficient_ != 0 and mixtureCoefficient_ != 1)) {
111 auto &inputTrees2ToUse
112 = (not isPersistenceDiagram_ ? inputTrees2 : inputTrees);
113 constructTrees(inputTrees2ToUse, intermediateTrees2, !useSecondPairsType,
114 DiagramPairTypes);
115 }
116
117 // Verify parameters
118 if(not UseFieldDataParameters) {
119 if(Backend == 0) {
122 keepSubtree_ = false;
123 baseModule_ = 0;
124 } else if(Backend == 1) {
125 branchDecomposition_ = false;
127 keepSubtree_ = true;
128 baseModule_ = 0;
129 } else if(Backend == 3) {
132 keepSubtree_ = true;
133 baseModule_ = 1;
134 } else if(Backend == 4) {
137 keepSubtree_ = true;
138 baseModule_ = 2;
139 } else {
140 baseModule_ = 0;
141 }
142 }
143 if(baseModule_ == 0) {
146 }
147 if(not branchDecomposition_) {
149 printMsg("NormalizedWasserstein is set to false since branch "
150 "decomposition is not asked.");
152 }
154 printMsg("Computation with normalized Wasserstein.");
155 else
156 printMsg("Computation without normalized Wasserstein.");
160 printMsg("BranchDecomposition: " + std::to_string(branchDecomposition_));
161 printMsg("NormalizedWasserstein: "
162 + std::to_string(normalizedWasserstein_));
163 printMsg("KeepSubtree: " + std::to_string(keepSubtree_));
164 }
165 if(baseModule_ == 1) {
166 printMsg("Using Branch Mapping Distance.");
167 std::string metric;
168 if(branchMetric_ == 0)
169 metric = "Wasserstein Distance first degree";
170 else if(branchMetric_ == 1)
171 metric = "Wasserstein Distance second degree";
172 else if(branchMetric_ == 2)
173 metric = "Persistence difference";
174 else if(branchMetric_ == 3)
175 metric = "Shifting cost";
176 else
177 return 1;
181 printMsg("BranchMetric: " + metric);
182 }
183 if(baseModule_ == 2) {
184 printMsg("Using Path Mapping Distance.");
185 std::string metric;
186 if(pathMetric_ == 0)
187 metric = "Persistence difference";
188 else
189 return 1;
193 printMsg("PathMetric: " + metric);
194 }
195
196 // --- Call base
197 std::vector<std::vector<double>> treesDistMat(
198 numInputs, std::vector<double>(numInputs));
199 execute<dataType>(intermediateTrees, intermediateTrees2, treesDistMat);
200
201 // --- Create output
202 auto treesDistTable = vtkTable::GetData(outputVector);
203
204 // zero-padd column name to keep Row Data columns ordered
205 const auto zeroPad
206 = [](std::string &colName, const size_t numberCols, const size_t colIdx) {
207 std::string const max{std::to_string(numberCols - 1)};
208 std::string const cur{std::to_string(colIdx)};
209 std::string const zer(max.size() - cur.size(), '0');
210 colName.append(zer).append(cur);
211 };
212
213 // copy trees distance matrix to output
214 vtkNew<vtkIntArray> treeIds{};
215 treeIds->SetName("treeID");
216 treeIds->SetNumberOfTuples(numInputs);
217 for(size_t i = 0; i < treesDistMat.size(); ++i) {
218 treeIds->SetTuple1(i, i);
219
220 std::string name{"Tree"};
221 zeroPad(name, treesDistMat.size(), i);
222 vtkNew<vtkDoubleArray> col{};
223 col->SetNumberOfTuples(numInputs);
224 col->SetName(name.c_str());
225 for(size_t j = 0; j < treesDistMat[i].size(); ++j) {
226 col->SetTuple1(j, treesDistMat[i][j]);
227 }
228 treesDistTable->AddColumn(col);
229 }
230
231 treesDistTable->AddColumn(treeIds);
232
233 // aggregate input field data
234 vtkNew<vtkFieldData> allFieldData{}, allFieldDataCopy{};
235 for(unsigned int i = 0; i < inputTrees.size(); ++i) {
236 for(unsigned int j = 0; j < inputTrees[i]->GetNumberOfBlocks(); ++j) {
237 auto fd = inputTrees[i]->GetBlock(j)->GetFieldData();
238 for(int k = 0; k < fd->GetNumberOfArrays(); ++k) {
239 auto array = fd->GetAbstractArray(k);
240 auto dataArray = vtkDataArray::SafeDownCast(array);
241 auto stringArray = vtkStringArray::SafeDownCast(array);
242 if(dataArray or stringArray)
243 allFieldData->AddArray(array);
244 }
245 }
246 }
247 allFieldDataCopy->DeepCopy(allFieldData); // to not modify original field data
248
249 for(int k = 0; k < allFieldDataCopy->GetNumberOfArrays(); ++k) {
250 auto array = allFieldDataCopy->GetAbstractArray(k);
251 array->SetNumberOfTuples(inputTrees.size());
252 auto dataArray = vtkDataArray::SafeDownCast(array);
253 auto stringArray = vtkStringArray::SafeDownCast(array);
254 auto name = array->GetName();
255 for(unsigned int i = 0; i < inputTrees.size(); ++i) {
256 bool foundArray = false;
257 for(unsigned int j = 0; j < inputTrees[i]->GetNumberOfBlocks(); ++j) {
258 auto inputArray
259 = inputTrees[i]->GetBlock(j)->GetFieldData()->GetAbstractArray(name);
260 if(inputArray) {
261 array->SetTuple(i, 0, inputArray);
262 foundArray = true;
263 } else if(not foundArray) {
264 if(dataArray) {
265 const double val = std::nan("");
266 dataArray->SetTuple(i, &val);
267 } else if(stringArray) {
268 stringArray->SetValue(i, "");
269 }
270 }
271 }
272 }
273 treesDistTable->AddColumn(array);
274 }
275
276 return 1;
277}
278
280 vtkInformation *ttkNotUsed(request),
281 vtkInformationVector **inputVector,
282 vtkInformationVector *outputVector) {
283 // --- Get input object from input vector
284 auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
285 auto blocks2 = vtkMultiBlockDataSet::GetData(inputVector[1], 0);
286
287 // --- Load blocks
288 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> inputTrees, inputTrees2;
289 loadBlocks(inputTrees, blocks);
290 loadBlocks(inputTrees2, blocks2);
291
292 // --- Load field data parameters
293 if(UseFieldDataParameters) {
294 printMsg("Load parameters from field data.");
295 std::vector<std::string> paramNames;
296 getParamNames(paramNames);
297 for(auto paramName : paramNames) {
298 auto array = blocks->GetFieldData()->GetArray(paramName.c_str());
299 if(array) {
300 double const value = array->GetTuple1(0);
301 setParamValueFromName(paramName, value);
302 printMsg(" - " + paramName + " = " + std::to_string(value));
303 } else
304 printMsg(" - " + paramName + " was not found in the field data.");
305 }
306 }
307
308 return run<float>(outputVector, inputTrees, inputTrees2);
309}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
TTK VTK-filter that wraps the ttk::MergeTreeDistanceMatrix module.
int FillInputPortInformation(int port, vtkInformation *info) override
~ttkMergeTreeDistanceMatrix() override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillOutputPortInformation(int port, vtkInformation *info) override
int run(vtkInformationVector *outputVector, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees2)
void setParamValueFromName(std::string &paramName, double value)
void getParamNames(std::vector< std::string > &paramNames)
void execute(std::vector< ftm::MergeTree< dataType > > &trees, std::vector< ftm::MergeTree< dataType > > &trees2, std::vector< std::vector< double > > &distanceMatrix)
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)
TTK base package defining the standard types.
vtkStandardNewMacro(ttkMergeTreeDistanceMatrix)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)