TTK
Loading...
Searching...
No Matches
ttkMergeTreeDistanceMatrix.cpp
Go to the documentation of this file.
1#include <ttkFTMTreeUtils.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 useSadMaxPairs = (mixtureCoefficient_ == 0); // only for PD support
107 = constructTrees(inputTrees, intermediateTrees, useSadMaxPairs);
109 or (mixtureCoefficient_ != 0 and mixtureCoefficient_ != 1)) {
110 auto &inputTrees2ToUse
111 = (not isPersistenceDiagram_ ? inputTrees2 : inputTrees);
112 constructTrees(inputTrees2ToUse, intermediateTrees2, !useSadMaxPairs);
113 }
114
115 // Verify parameters
116 if(not UseFieldDataParameters) {
117 if(Backend == 0) {
120 keepSubtree_ = false;
121 baseModule_ = 0;
122 } else if(Backend == 1) {
123 branchDecomposition_ = false;
125 keepSubtree_ = true;
126 baseModule_ = 0;
127 } else if(Backend == 3) {
130 keepSubtree_ = true;
131 baseModule_ = 1;
132 } else if(Backend == 4) {
135 keepSubtree_ = true;
136 baseModule_ = 2;
137 } else {
138 baseModule_ = 0;
139 }
140 }
141 if(baseModule_ == 0) {
144 }
145 if(not branchDecomposition_) {
147 printMsg("NormalizedWasserstein is set to false since branch "
148 "decomposition is not asked.");
150 }
152 printMsg("Computation with normalized Wasserstein.");
153 else
154 printMsg("Computation without normalized Wasserstein.");
158 printMsg("BranchDecomposition: " + std::to_string(branchDecomposition_));
159 printMsg("NormalizedWasserstein: "
160 + std::to_string(normalizedWasserstein_));
161 printMsg("KeepSubtree: " + std::to_string(keepSubtree_));
162 }
163 if(baseModule_ == 1) {
164 printMsg("Using Branch Mapping Distance.");
165 std::string metric;
166 if(branchMetric_ == 0)
167 metric = "Wasserstein Distance first degree";
168 else if(branchMetric_ == 1)
169 metric = "Wasserstein Distance second degree";
170 else if(branchMetric_ == 2)
171 metric = "Persistence difference";
172 else if(branchMetric_ == 3)
173 metric = "Shifting cost";
174 else
175 return 1;
176 printMsg("BranchMetric: " + metric);
177 }
178 if(baseModule_ == 2) {
179 printMsg("Using Path Mapping Distance.");
180 std::string metric;
181 if(pathMetric_ == 0)
182 metric = "Persistence difference";
183 else
184 return 1;
185 printMsg("PathMetric: " + metric);
186 }
187
188 // --- Call base
189 std::vector<std::vector<double>> treesDistMat(
190 numInputs, std::vector<double>(numInputs));
191 if(baseModule_ == 0)
192 execute<dataType>(intermediateTrees, intermediateTrees2, treesDistMat);
193 else
194 execute<dataType>(intermediateTrees, treesDistMat);
195
196 // --- Create output
197 auto treesDistTable = vtkTable::GetData(outputVector);
198
199 // zero-padd column name to keep Row Data columns ordered
200 const auto zeroPad
201 = [](std::string &colName, const size_t numberCols, const size_t colIdx) {
202 std::string max{std::to_string(numberCols - 1)};
203 std::string cur{std::to_string(colIdx)};
204 std::string zer(max.size() - cur.size(), '0');
205 colName.append(zer).append(cur);
206 };
207
208 // copy trees distance matrix to output
209 vtkNew<vtkIntArray> treeIds{};
210 treeIds->SetName("treeID");
211 treeIds->SetNumberOfTuples(numInputs);
212 for(size_t i = 0; i < treesDistMat.size(); ++i) {
213 treeIds->SetTuple1(i, i);
214
215 std::string name{"Tree"};
216 zeroPad(name, treesDistMat.size(), i);
217 vtkNew<vtkDoubleArray> col{};
218 col->SetNumberOfTuples(numInputs);
219 col->SetName(name.c_str());
220 for(size_t j = 0; j < treesDistMat[i].size(); ++j) {
221 col->SetTuple1(j, treesDistMat[i][j]);
222 }
223 treesDistTable->AddColumn(col);
224 }
225
226 treesDistTable->AddColumn(treeIds);
227
228 // aggregate input field data
229 vtkNew<vtkFieldData> allFieldData{}, allFieldDataCopy{};
230 for(unsigned int i = 0; i < inputTrees.size(); ++i) {
231 for(unsigned int j = 0; j < inputTrees[i]->GetNumberOfBlocks(); ++j) {
232 auto fd = inputTrees[i]->GetBlock(j)->GetFieldData();
233 for(int k = 0; k < fd->GetNumberOfArrays(); ++k) {
234 auto array = fd->GetAbstractArray(k);
235 auto dataArray = vtkDataArray::SafeDownCast(array);
236 auto stringArray = vtkStringArray::SafeDownCast(array);
237 if(dataArray or stringArray)
238 allFieldData->AddArray(array);
239 }
240 }
241 }
242 allFieldDataCopy->DeepCopy(allFieldData); // to not modify original field data
243
244 for(int k = 0; k < allFieldDataCopy->GetNumberOfArrays(); ++k) {
245 auto array = allFieldDataCopy->GetAbstractArray(k);
246 array->SetNumberOfTuples(inputTrees.size());
247 auto dataArray = vtkDataArray::SafeDownCast(array);
248 auto stringArray = vtkStringArray::SafeDownCast(array);
249 auto name = array->GetName();
250 for(unsigned int i = 0; i < inputTrees.size(); ++i) {
251 bool foundArray = false;
252 for(unsigned int j = 0; j < inputTrees[i]->GetNumberOfBlocks(); ++j) {
253 auto inputArray
254 = inputTrees[i]->GetBlock(j)->GetFieldData()->GetAbstractArray(name);
255 if(inputArray) {
256 array->SetTuple(i, 0, inputArray);
257 foundArray = true;
258 } else if(not foundArray) {
259 if(dataArray) {
260 const double val = std::nan("");
261 dataArray->SetTuple(i, &val);
262 } else if(stringArray) {
263 stringArray->SetValue(i, "");
264 }
265 }
266 }
267 }
268 treesDistTable->AddColumn(array);
269 }
270
271 return 1;
272}
273
275 vtkInformation *ttkNotUsed(request),
276 vtkInformationVector **inputVector,
277 vtkInformationVector *outputVector) {
278 // --- Get input object from input vector
279 auto blocks = vtkMultiBlockDataSet::GetData(inputVector[0], 0);
280 auto blocks2 = vtkMultiBlockDataSet::GetData(inputVector[1], 0);
281
282 // --- Load blocks
283 std::vector<vtkSmartPointer<vtkMultiBlockDataSet>> inputTrees, inputTrees2;
284 loadBlocks(inputTrees, blocks);
285 loadBlocks(inputTrees2, blocks2);
286
287 // --- Load field data parameters
288 if(UseFieldDataParameters) {
289 printMsg("Load parameters from field data.");
290 std::vector<std::string> paramNames;
291 getParamNames(paramNames);
292 for(auto paramName : paramNames) {
293 auto array = blocks->GetFieldData()->GetArray(paramName.c_str());
294 if(array) {
295 double value = array->GetTuple1(0);
296 setParamValueFromName(paramName, value);
297 printMsg(" - " + paramName + " = " + std::to_string(value));
298 } else
299 printMsg(" - " + paramName + " was not found in the field data.");
300 }
301 }
302
303 return run<float>(outputVector, inputTrees, inputTrees2);
304}
#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)
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
Definition: Debug.h:118
double mixtureCoefficient_
Definition: MergeTreeBase.h:51
void setParamValueFromName(std::string &paramName, double value)
void getParamNames(std::vector< std::string > &paramNames)
bool constructTrees(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, std::vector< MergeTree< dataType > > &intermediateTrees, std::vector< vtkUnstructuredGrid * > &treesNodes, std::vector< vtkUnstructuredGrid * > &treesArcs, std::vector< vtkDataSet * > &treesSegmentation, std::vector< bool > useSadMaxPairs)
void loadBlocks(std::vector< vtkSmartPointer< vtkMultiBlockDataSet > > &inputTrees, vtkMultiBlockDataSet *blocks)
The Topology ToolKit.
vtkStandardNewMacro(ttkMergeTreeDistanceMatrix)