TTK
Loading...
Searching...
No Matches
UncertainDataEstimator.h
Go to the documentation of this file.
1
11
12#pragma once
13
14// base code includes
15#include <Wrapper.h>
16
17namespace ttk {
18
19 template <class dataType>
20 class PDFBounds : virtual public Debug {
21 public:
22 int evaluateRealization(const void *voidPointer) {
23#ifndef TTK_ENABLE_KAMIKAZE
24 if(!(numberOfVertices_ > 0)) {
25 return -1; // Number of vertices not defined
26 }
27#endif
28 const dataType *inputData
29 = reinterpret_cast<const dataType *>(voidPointer);
30 auto numberOfVertices = static_cast<size_t>(numberOfVertices_);
31 /* Initialize if first call since a change */
32 if(!(upperBound_.size() == numberOfVertices)
33 || !(lowerBound_.size() == numberOfVertices)) {
34 upperBound_.resize(numberOfVertices);
35 lowerBound_.resize(numberOfVertices);
36#ifdef TTK_ENABLE_OPENMP
37#pragma omp parallel for num_threads(threadNumber_)
38#endif
39 for(size_t i = 0; i < numberOfVertices; i++) {
40 upperBound_[i] = inputData[i];
41 lowerBound_[i] = inputData[i];
42 }
43 } else { /* Update the two fields with the new input */
44#ifdef TTK_ENABLE_OPENMP
45#pragma omp parallel for num_threads(threadNumber_)
46#endif
47 for(size_t i = 0; i < numberOfVertices; i++) {
48 // Upper Bound
49 if(inputData[i] > upperBound_[i]) {
50 upperBound_[i] = inputData[i];
51 }
52 // Lower Bound
53 if(inputData[i] < lowerBound_[i]) {
54 lowerBound_[i] = inputData[i];
55 }
56 }
57 }
58 return 0;
59 }
60
61 std::pair<dataType, dataType> getRange() const {
62 return {getRangeMin(), getRangeMax()};
63 }
64
65 dataType getRangeMax() const {
66 if(upperBound_.size()) {
67 dataType maxValue = upperBound_[0];
68 for(size_t i = 1; i < upperBound_.size(); i++) {
69 if(upperBound_[i] > maxValue) {
70 maxValue = upperBound_[i];
71 }
72 }
73 return maxValue;
74 } else {
75 return 0;
76 }
77 }
78
79 dataType getRangeMin() const {
80 if(lowerBound_.size()) {
81 dataType minValue = lowerBound_[0];
82 for(size_t i = 1; i < lowerBound_.size(); i++) {
83 if(lowerBound_[i] < minValue) {
84 minValue = lowerBound_[i];
85 }
86 }
87 return minValue;
88 } else {
89 return 0;
90 }
91 }
92
93 inline dataType *getLowerBoundPointer() {
94 return lowerBound_.data();
95 }
96
97 inline dataType *getUpperBoundPointer() {
98 return upperBound_.data();
99 }
100
101 inline void setNumberOfVertices(const SimplexId number) {
102 numberOfVertices_ = number;
103 }
104
105 protected:
107 std::vector<dataType> upperBound_{};
108 std::vector<dataType> lowerBound_{};
109 };
110
111 class PDFHistograms : virtual public Debug {
112 public:
113 template <class dataType>
114 int evaluateRealization(const dataType *inputData) {
115#ifndef TTK_ENABLE_KAMIKAZE
116 if(!(rangeMin_ < rangeMax_)) {
117 return -1; // Range error
118 }
119 if(!(numberOfBins_ > 0)) {
120 return -2; // Number of bins not defined
121 }
122 if(!(numberOfVertices_ > 0)) {
123 return -3; // Number of vertices not defined
124 }
125#endif
126 if(numberOfInputs_ == 0) {
127 /* Initialize */
129 double const dx
130 = (rangeMax_ - rangeMin_) / static_cast<double>(numberOfBins_);
131 for(size_t i = 0; i < static_cast<size_t>(numberOfBins_); i++) {
133 binValue_[i] = rangeMin_ + (dx / 2.0) + (static_cast<double>(i) * dx);
134 }
135 }
136 /* Add input data */
137 for(SimplexId i = 0; i < numberOfVertices_; i++) {
138 int bin
139 = static_cast<int>(floor((inputData[i] - rangeMin_) * numberOfBins_
140 / (rangeMax_ - rangeMin_)));
141 bin = (bin == numberOfBins_) ? numberOfBins_ - 1 : bin;
142 probability_[bin][i] += 1.0;
143 }
145 return 0;
146 }
147
148 inline double *getBinFieldPointer(const int binId) {
149 if(binId < numberOfBins_) {
150 return probability_[binId].data();
151 } else {
152 return nullptr;
153 }
154 }
155
156 void getVertexHistogram(const SimplexId vertexId,
157 std::vector<double> &histogram) const;
158
159 void normalize();
160
161 inline void setNumberOfBins(const int number) {
162 numberOfBins_ = number;
163 }
164
165 inline void setNumberOfVertices(const SimplexId number) {
166 numberOfVertices_ = number;
167 }
168
169 inline void setRange(const double min, const double max) {
170 rangeMin_ = min;
171 rangeMax_ = max;
172 }
173
174 protected:
175 std::vector<double> binValue_{};
176 std::vector<std::vector<double>> probability_{};
180 double rangeMin_{0.0};
181 double rangeMax_{0.0};
182 // std::vector<int> selection_; // TODO : selection support
183 };
184
185 class UncertainDataEstimator : virtual public Debug {
186 public:
188
191 template <class dataType>
192 int execute();
193
199 inline int setInputDataPointer(const int idx, void *const data) {
200 if(idx < numberOfInputs_) {
201 inputData_[idx] = data;
202 } else {
203 return -1;
204 }
205 return 0;
206 }
207
212 inline void setOutputLowerBoundField(void *const data) {
214 }
215
220 inline void setOutputUpperBoundField(void *const data) {
222 }
223
224 inline void setOutputProbability(const int idx, double *const data) {
225 if(idx < BinCount) {
226 outputProbability_[idx] = data;
227 }
228 }
229
230 inline void setOutputMeanField(void *const data) {
231 outputMeanField_ = data;
232 }
233
234 inline void setComputeLowerBound(const bool state) {
235 ComputeLowerBound = state;
236 }
237
238 inline void setComputeUpperBound(const bool state) {
239 ComputeUpperBound = state;
240 }
241
245 inline void setVertexNumber(const SimplexId &vertexNumber) {
246 vertexNumber_ = vertexNumber;
247 }
248
249 inline void setBinCount(const int binCount) {
250 BinCount = binCount;
251 outputProbability_.clear();
252 outputProbability_.resize(binCount, nullptr);
253 binValues_.clear();
254 binValues_.resize(binCount);
255 }
256
260 inline void setNumberOfInputs(const int numberOfInputs) {
261 numberOfInputs_ = numberOfInputs;
262 inputData_.clear();
263 inputData_.resize(numberOfInputs, nullptr);
264 }
265
266 inline double getBinValue(int b) {
267 if(b < BinCount)
268 return binValues_[b];
269 return 0.0;
270 }
271
272 protected:
275 int BinCount{0};
276 std::vector<double> binValues_{};
279 std::vector<void *> inputData_{};
282 std::vector<double *> outputProbability_{};
284 };
285} // namespace ttk
286
287template <class dataType>
289
290 Timer t;
291
292 // Check the consistency of the variables
293#ifndef TTK_ENABLE_KAMIKAZE
294 if(!numberOfInputs_)
295 return -1;
296 if(!vertexNumber_)
297 return -2;
298
299 for(int i = 0; i < numberOfInputs_; i++) {
300 if(!inputData_[i])
301 return -4;
302 }
304 return -5;
306 return -6;
307#endif
308
309 SimplexId count = 0;
310
311 // Pointers type casting
312 dataType *outputLowerBoundField = (dataType *)outputLowerBoundField_;
313 dataType *outputUpperBoundField = (dataType *)outputUpperBoundField_;
314 dataType **inputData = (dataType **)inputData_.data();
315 double *outputMeanField = static_cast<double *>(outputMeanField_);
316
317#ifdef TTK_ENABLE_OPENMP
318#pragma omp parallel for num_threads(threadNumber_)
319#endif
320 for(SimplexId v = 0; v < (SimplexId)vertexNumber_; v++) {
321
322 // Avoid any processing if the abort signal is sent
323 if((!wrapper_) || ((wrapper_) && (!wrapper_->needsToAbort()))) {
324
325 // For the lower bound scalar field
327 // Initialisation : values of the first input
328 outputLowerBoundField[v] = inputData[0][v];
329 // Loop over the inputs
330 for(int inp = 1; inp < numberOfInputs_; inp++) {
331 // Minimum value
333 if(inputData[inp][v] < outputLowerBoundField[v])
334 outputLowerBoundField[v] = inputData[inp][v];
335 }
336 }
337
338 // For the upper bound scalar field
340 // Initialisation : values of the first input
341 outputUpperBoundField[v] = inputData[0][v];
342 // Loop over the inputs
343 for(int inp = 1; inp < numberOfInputs_; inp++) {
344 // Maximum value
346 if(inputData[inp][v] > outputUpperBoundField[v])
347 outputUpperBoundField[v] = inputData[inp][v];
348 }
349 }
350
351 // Update the progress bar of the wrapping code -- to adapt
352 if(debugLevel_ > static_cast<int>(debug::Priority::DETAIL)) {
353#ifdef TTK_ENABLE_OPENMP
354#pragma omp critical
355#endif
356 {
357 if((wrapper_) && (!(count % ((vertexNumber_) / 10)))) {
358 wrapper_->updateProgress((count + 1.0) / vertexNumber_);
359 }
360
361 count++;
362 }
363 }
364 }
365 }
366
367 // Histogram
369 // Range
370 double range[2];
371 range[0] = outputLowerBoundField[0];
372 range[1] = outputUpperBoundField[0];
373
374 for(SimplexId v = 0; v < vertexNumber_; v++) {
375 if(outputLowerBoundField[v] < range[0])
376 range[0] = outputLowerBoundField[v];
377 if(outputUpperBoundField[v] > range[1])
378 range[1] = outputUpperBoundField[v];
379 }
380
381 // Interval between bins
382 double const dx = (range[1] - range[0]) / (double)BinCount;
383
384 // Bin values
385 for(int b = 0; b < BinCount; b++) {
386 binValues_[b] = range[0] + (dx / 2.0) + (double)b * dx;
387 }
388
389 int idx;
390 double const increment = 1.0 / (double)numberOfInputs_;
391#ifdef TTK_ENABLE_OPENMP
392#pragma omp parallel for private(idx) num_threads(threadNumber_)
393#endif
394 for(SimplexId v = 0; v < vertexNumber_; v++) {
395 for(int i = 0; i < numberOfInputs_; i++) {
396 idx = (int)floor((inputData[i][v] - range[0]) * BinCount
397 / (range[1] - range[0]));
398 idx = (idx == BinCount) ? BinCount - 1 : idx;
399 outputProbability_[idx][v] += increment;
400 }
401 }
402 }
403
404 // Mean field
405 for(SimplexId v = 0; v < vertexNumber_; v++) {
406 double sum = 0.0;
407 for(int i = 0; i < numberOfInputs_; i++) {
408 sum += static_cast<double>(inputData[i][v]);
409 }
410 outputMeanField[v] = sum / static_cast<double>(numberOfInputs_);
411 }
412
413 this->printMsg(std::vector<std::vector<std::string>>{
414 {"#Vertices", std::to_string(vertexNumber_)}});
415 this->printMsg(
416 "Data-set processed", 1.0, t.getElapsedTime(), this->threadNumber_);
417
418 return 0;
419}
Wrapper * wrapper_
Definition BaseClass.h:96
Minimalist debugging class.
Definition Debug.h:88
int debugLevel_
Definition Debug.h:379
std::vector< dataType > lowerBound_
void setNumberOfVertices(const SimplexId number)
dataType getRangeMax() const
dataType * getUpperBoundPointer()
std::vector< dataType > upperBound_
dataType * getLowerBoundPointer()
int evaluateRealization(const void *voidPointer)
dataType getRangeMin() const
std::pair< dataType, dataType > getRange() const
void getVertexHistogram(const SimplexId vertexId, std::vector< double > &histogram) const
void setNumberOfVertices(const SimplexId number)
std::vector< double > binValue_
int evaluateRealization(const dataType *inputData)
void setRange(const double min, const double max)
double * getBinFieldPointer(const int binId)
std::vector< std::vector< double > > probability_
void setNumberOfBins(const int number)
double getElapsedTime()
Definition Timer.h:15
TTK processing package that takes an input ensemble data set (represented by a list of scalar fields)...
std::vector< double * > outputProbability_
void setOutputLowerBoundField(void *const data)
void setOutputMeanField(void *const data)
void setVertexNumber(const SimplexId &vertexNumber)
int setInputDataPointer(const int idx, void *const data)
void setComputeUpperBound(const bool state)
void setBinCount(const int binCount)
void setOutputUpperBoundField(void *const data)
void setOutputProbability(const int idx, double *const data)
void setNumberOfInputs(const int numberOfInputs)
void setComputeLowerBound(const bool state)
virtual int updateProgress(const float &progress)=0
virtual bool needsToAbort()=0
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)