Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TKDTreeBinning.cxx
Go to the documentation of this file.
1// @(#)root/mathcore:$Id$
2// Authors: B. Rabacal 11/2010
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2010 , LCG ROOT MathLib Team *
7 * *
8 * *
9 **********************************************************************/
10
11// implementation file for class TKDTreeBinning
12//
13
14#include <algorithm>
15#include <limits>
16#include <cmath>
17
18#include "TKDTreeBinning.h"
19
20#include "Fit/BinData.h"
21#include "TBuffer.h"
22
23
24/**
25\class TKDTreeBinning
26A class providing multidimensional binning
27
28The class implements multidimensional binning by constructing a TKDTree inner structure from the
29data which is used as the bins.
30The bins are retrieved as two double*, one for the minimum bin edges,
31the other as the maximum bin edges. For one dimension one of these is enough to correctly define the bins.
32For the multidimensional case both minimum and maximum ones are necessary for the bins to be well defined.
33The bin edges of d-dimensional data is a d-tet of the bin's thresholds. For example if d=3 the minimum bin
34edges of bin b is of the form of the following array: {xbmin, ybmin, zbmin}.
35You also have the possibility to sort the bins by their density.
36
37kdTreeBinning.C and more information on
38the embedded TKDTree documentation.
39
40@ingroup MathCore
41
42*/
43
45 // Boolean functor whose predicate depends on the bin's density. Used for ascending sort.
48 return bins->GetBinDensity(bin1) < bins->GetBinDensity(bin2);
49 }
51};
52
54 // Boolean functor whose predicate depends on the bin's density. Used for descending sort.
57 return bins->GetBinDensity(bin1) > bins->GetBinDensity(bin2);
58 }
60};
61
62/// Class's constructor taking the size of the data points, dimension, a data array and the number
63/// of bins (default = 100). It is recommended to have the number of bins as an exact divider of
64/// the data size.
65/// The data array must be organized with a stride=1 for the points and = N (the dataSize) for the dimension.
66///
67/// Thus data[] = x1,x2,x3,......xN, y1,y2,y3......yN, z1,z2,...........zN,....
68///
69/// Note that the passed dataSize is not the size of the array but is the number of points (N)
70/// The size of the array must be at least dataDim*dataSize
71///
73: fData(0), fDataBins((TKDTreeID*)nullptr), fDim(dataDim),
74fDataSize(dataSize), fDataThresholds(std::vector<std::pair<Double_t, Double_t> >(fDim, std::make_pair(0., 0.))),
75fIsSorted(kFALSE), fIsSortedAsc(kFALSE) {
77 if (data) {
79 SetNBins(nBins);
80 } else {
81 if (fData.empty())
82 this->Warning("TKDTreeBinning", "Data is nil. Nothing is built.");
83 }
84}
85/// Class's constructor taking the size of the data points, dimension, a data vector and the number
86/// of bins (default = 100). It is recommended to have the number of bins as an exact divider of
87/// the data size.
88/// The data array must be organized with a stride=1 for the points and = N (the dataSize) for the dimension.
89///
90/// Thus data[] = x1,x2,x3,......xN, y1,y2,y3......yN, z1,z2,...........zN,....
91///
92/// Note that the passed data vector may contains a larger size, in case extra coordinates are associated but not used
93/// in building the kdtree
94/// The size of thedata vector must be at least dataDim*dataSize
95///
97: fData(0), fDataBins((TKDTreeID*)nullptr), fNBins (nBins), fDim(dataDim),
98fDataSize(dataSize), fDataThresholds(std::vector<std::pair<Double_t, Double_t> >(fDim, std::make_pair(0., 0.))),
99fIsSorted(kFALSE), fIsSortedAsc(kFALSE) {
101 if (!data.empty()) {
102 SetData(data);
103 SetNBins(nBins);
104 } else {
105 if (fData.empty())
106 this->Warning("TKDTreeBinning", "Data is nil. Nothing is built.");
107 }
108}
109
110/// Default constructor (for I/O)
112// fData(nullptr),
113 fDataBins(nullptr),
114 fNBins (0),
115 fDim(0),
116 fDataSize(0),
117 fIsSorted(kFALSE), fIsSortedAsc(kFALSE)
118{}
119
120/// Class's destructor
122 // if (fData) delete[] fData;
123 if (fDataBins) delete fDataBins;
124}
125
126/// Sets binning inner structure
128 fNBins = bins;
129 if (fDim && fNBins && fDataSize) {
130 if (fDataSize / fNBins) {
132 if (remainingData) {
133 fNBins += 1;
134 this->Info("SetNBins", "Number of bins is not enough to hold the data. Extra bin added.");
135 }
136 fDataBins = new TKDTreeID(fDataSize, fDim, fDataSize / (fNBins - remainingData)); // TKDTree input is data size, data dimension and the content size of bins ("bucket" size)
137 SetTreeData();
138 fDataBins->Build();
139 // Need to keep the number of bins consistent with the number of
140 // terminal nodes in the kd-tree.
141 fNBins = fDataBins->GetNNodes() + 1;
142 SetBinsEdges();
144 } else {
145 fDataBins = (TKDTreeID*)nullptr;
146 this->Warning("SetNBins", "Number of bins is bigger than data size. Nothing is built.");
147 }
148 } else {
149 fDataBins = (TKDTreeID*)nullptr;
150 if (!fDim)
151 this->Warning("SetNBins", "Data dimension is nil. Nothing is built.");
152 if (!fNBins)
153 this->Warning("SetNBins", "Number of bins is nil. Nothing is built.");
154 if (!fDataSize)
155 this->Warning("SetNBins", "Data size is nil. Nothing is built.");
156 }
157}
158
159/// Sorts bins by their density
161 if (fDim == 1) {
162 // in one dim they are already sorted (no need to do anything)
163 return;
164 } else {
165 std::vector<UInt_t> indices(fNBins); // vector for indices (for the inverse transformation)
166 for (UInt_t i = 0; i < fNBins; ++i)
167 indices[i] = i;
168 if (sortAsc) {
169 std::sort(indices.begin(), indices.end(), CompareAsc(this));
171 } else {
172 std::sort(indices.begin(), indices.end(), CompareDesc(this));
174 }
175 std::vector<Double_t> binMinEdges(fNBins * fDim);
176 std::vector<Double_t> binMaxEdges(fNBins * fDim);
177 std::vector<UInt_t> binContent(fNBins ); // readjust also content (not needed but better in general!)
178 fIndices.resize(fNBins);
179 for (UInt_t i = 0; i < fNBins; ++i) {
180 for (UInt_t j = 0; j < fDim; ++j) {
181 binMinEdges[i * fDim + j] = fBinMinEdges[indices[i] * fDim + j];
182 binMaxEdges[i * fDim + j] = fBinMaxEdges[indices[i] * fDim + j];
183 }
184 binContent[i] = fBinsContent[indices[i]];
185 fIndices[indices[i]] = i;
186 }
190
191 // not needed anymore if readjusting bin content all the time
192 // re-adjust content of extra bins if exists
193 // since it is different than the others
194 // if ( fDataSize % fNBins != 0) {
195 // UInt_t k = 0;
196 // Bool_t found = kFALSE;
197 // while (!found) {
198 // if (indices[k] == fNBins - 1) {
199 // found = kTRUE;
200 // break;
201 // }
202 // ++k;
203 // }
204 // fBinsContent[fNBins - 1] = fDataBins->GetBucketSize();
205 // fBinsContent[k] = fDataSize % fNBins-1;
206 // }
207
209 }
210}
211
213 // Sets the data and finds minimum and maximum by dimensional coordinate
214 fData.resize(fDim*fDataSize);
215 auto first = fData.begin();
216 for (UInt_t i = 0; i < fDim; ++i) {
217 for (UInt_t j = 0; j < fDataSize; ++j) {
218 fData[i*fDataSize+j] = data[i * fDataSize + j];
219 }
220 auto end = first+fDataSize;
221 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
222 first = end;
223 }
224}
225void TKDTreeBinning::SetData(const std::vector<double>& data) {
226 // Sets the data and finds minimum and maximum by dimensional coordinate
227 fData = data;
228 auto first = fData.begin();
229 // find min/max
230 for (UInt_t i = 0; i < fDim; ++i) {
231 auto end = first+fDataSize;
232 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
233 first = end;
234 }
235}
236
238 // Sets the data for constructing the kD-tree
239 for (UInt_t i = 0; i < fDim; ++i)
240 fDataBins->SetData(i, &fData[i*fDataSize]);
241}
242
244 // Sets the bins' content from the actual number of points in each terminal
245 // node of the kd-tree. All terminal nodes hold fBucketSize points except
246 // possibly the last one, so query the tree directly instead of guessing.
247 fBinsContent.resize(fNBins);
248 UInt_t nTreeNodes = fDataBins->GetNNodes();
249 for (UInt_t i = 0; i < fNBins; ++i)
250 fBinsContent[i] = fDataBins->GetNPointsNode(i + nTreeNodes);
251}
252
254 // Sets the bins' edges
255 //Double_t* rawBinEdges = fDataBins->GetBoundaryExact(fDataBins->GetNNodes());
256 Double_t* rawBinEdges = fDataBins->GetBoundary(fDataBins->GetNNodes());
257 fCheckedBinEdges = std::vector<std::vector<std::pair<Bool_t, Bool_t> > >(fDim, std::vector<std::pair<Bool_t, Bool_t> >(fNBins, std::make_pair(kFALSE, kFALSE)));
258 fCommonBinEdges = std::vector<std::map<Double_t, std::vector<UInt_t> > >(fDim, std::map<Double_t, std::vector<UInt_t> >());
260 if (TestBit(kAdjustBinEdges) ) {
263 }
265 fCommonBinEdges.clear();
266 fCheckedBinEdges.clear();
267}
268
270 // Sets the bins' minimum and maximum edges
271 fBinMinEdges.reserve(fNBins * fDim);
272 fBinMaxEdges.reserve(fNBins * fDim);
273 for (UInt_t i = 0; i < fNBins; ++i) {
274 for (UInt_t j = 0; j < fDim; ++j) {
275 fBinMinEdges.push_back(binEdges[(i * fDim + j) * 2]);
276 fBinMaxEdges.push_back(binEdges[(i * fDim + j) * 2 + 1]);
277 }
278 }
279}
280
282 // Sets indexing on the bin edges which have common boundaries
283 for (UInt_t i = 0; i < fDim; ++i) {
284 for (UInt_t j = 0; j < fNBins; ++j) {
285 Double_t binEdge = binEdges[(j * fDim + i) * 2];
286 if(fCommonBinEdges[i].find(binEdge) == fCommonBinEdges[i].end()) {
287 std::vector<UInt_t> commonBinEdges;
288 for (UInt_t k = 0; k < fNBins; ++k) {
289 UInt_t minBinEdgePos = (k * fDim + i) * 2;
290 if (std::fabs(binEdge - binEdges[minBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
291 commonBinEdges.push_back(minBinEdgePos);
293 if (std::fabs(binEdge - binEdges[maxBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
294 commonBinEdges.push_back(maxBinEdgePos);
295 }
297 }
298 }
299 }
300}
301
303 // Readjusts the bins' minimum edge by shifting it slightly lower
304 // to avoid overlapping with the data
305 for (UInt_t i = 0; i < fDim; ++i) {
306 for (UInt_t j = 0; j < fNBins; ++j) {
307 if (!fCheckedBinEdges[i][j].first) {
308 Double_t binEdge = binEdges[(j * fDim + i) * 2];
310 double eps = -10*std::numeric_limits<Double_t>::epsilon();
311 if (adjustedBinEdge != 0)
312 adjustedBinEdge *= (1. + eps);
313 else
314 adjustedBinEdge += eps;
315
316 for (UInt_t k = 0; k < fCommonBinEdges[i][binEdge].size(); ++k) {
318 Bool_t isMinBinEdge = binEdgePos % 2 == 0;
319 UInt_t bin = isMinBinEdge ? (binEdgePos / 2 - i) / fDim : ((binEdgePos - 1) / 2 - i) / fDim;
320 binEdges[binEdgePos] = adjustedBinEdge;
321 if (isMinBinEdge)
322 fCheckedBinEdges[i][bin].first = kTRUE;
323 else
324 fCheckedBinEdges[i][bin].second = kTRUE;
325 }
326 }
327 }
328 }
329}
330
332 // Readjusts the bins' maximum edge
333 // and shift it slightly higher
334 for (UInt_t i = 0; i < fDim; ++i) {
335 for (UInt_t j = 0; j < fNBins; ++j) {
336 if (!fCheckedBinEdges[i][j].second) {
337 Double_t& binEdge = binEdges[(j * fDim + i) * 2 + 1];
338 double eps = 10*std::numeric_limits<Double_t>::epsilon();
339 if (binEdge != 0)
340 binEdge *= (1. + eps);
341 else
342 binEdge += eps;
343
344
345 }
346 }
347 }
348}
349
350/// Returns an array with all bins' minimum edges
351/// The edges are arranges as xmin_1,ymin_1, xmin_2,ymin_2,....xmin_{nbin},ymin_{nbin}
353 if (fDataBins)
354 return &fBinMinEdges[0];
355 this->Warning("GetBinsMinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
356 this->Info("GetBinsMinEdges", "Returning null pointer.");
357 return (Double_t*)nullptr;
358}
359
360/// Returns an array with all bins' maximum edges
361/// The edges are arranges as xmax_1,ymax_1, xmax_2,ymax_2,....xmax_{nbin},ymax_{nbin}
363 // Returns the bins' maximum edges
364 if (fDataBins)
365 return &fBinMaxEdges[0];
366 this->Warning("GetBinsMaxEdges", "Binning kd-tree is nil. No bin edges retrieved.");
367 this->Info("GetBinsMaxEdges", "Returning null pointer.");
368 return (Double_t*)nullptr;
369}
370
371/// Returns a pair of an array with all bins minimum and maximum edges
372std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinsEdges() const {
373 // Returns the bins' edges
374 if (fDataBins)
375 return std::make_pair(GetBinsMinEdges(), GetBinsMaxEdges());
376 this->Warning("GetBinsEdges", "Binning kd-tree is nil. No bin edges retrieved.");
377 this->Info("GetBinsEdges", "Returning null pointer pair.");
378 return std::make_pair((Double_t*)nullptr, (Double_t*)nullptr);
379}
380
381/// Returns the bin's minimum edges. 'bin' is between 0 and fNBins - 1
383 if (fDataBins)
384 if (bin < fNBins)
385 return &fBinMinEdges[bin * fDim];
386 else
387 this->Warning("GetBinMinEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
388 else
389 this->Warning("GetBinMinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
390 this->Info("GetBinMinEdges", "Returning null pointer.");
391 return (Double_t*)nullptr;
392}
393
394/// Returns the bin's maximum edges. 'bin' is between 0 and fNBins - 1
396 if (fDataBins)
397 if (bin < fNBins)
398 return &fBinMaxEdges[bin * fDim];
399 else
400 this->Warning("GetBinMaxEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
401 else
402 this->Warning("GetBinMaxEdges", "Binning kd-tree is nil. No bin edges retrieved.");
403 this->Info("GetBinMaxEdges", "Returning null pointer.");
404 return (Double_t*)nullptr;
405}
406
407/// Returns a pir with the bin's edges. 'bin' is between 0 and fNBins - 1
408std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinEdges(UInt_t bin) const {
409 if (fDataBins)
410 if (bin < fNBins)
411 return std::make_pair(GetBinMinEdges(bin), GetBinMaxEdges(bin));
412 else
413 this->Warning("GetBinEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
414 else
415 this->Warning("GetBinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
416 this->Info("GetBinEdges", "Returning null pointer pair.");
417 return std::make_pair((Double_t*)nullptr, (Double_t*)nullptr);
418}
419
420/// Returns the number of bins
422 return fNBins;
423}
424
425/// Returns the number of dimensions
427 return fDim;
428}
429
430/// Returns the number of points in bin. 'bin' is between 0 and fNBins - 1
432 if(bin <= fNBins - 1)
433 return fBinsContent[bin];
434 this->Warning("GetBinContent", "No such bin. Returning 0.");
435 this->Info("GetBinContent", "'bin' is between 0 and %d.", fNBins - 1);
436 return 0;
437}
438
439
440/// Returns the kD-Tree structure of the binning
442 if (fDataBins)
443 return fDataBins;
444 this->Warning("GetTree", "Binning kd-tree is nil. No embedded kd-tree retrieved. Returning null pointer.");
445 return (TKDTreeID*)nullptr;
446}
447
448// Returns the data array in the dim coordinate. 'dim' is between 0 and fDim - 1
450 if(dim < fDim)
451 return &fData[dim*fDataSize];
452 this->Warning("GetDimData", "No such dimensional coordinate. No coordinate data retrieved. Returning null pointer.");
453 this->Info("GetDimData", "'dim' is between 0 and %d.", fDim - 1);
454 return nullptr;
455}
456
457/// Returns the minimum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1
459 if(dim < fDim)
460 return fDataThresholds[dim].first;
461 this->Warning("GetDataMin", "No such dimensional coordinate. No coordinate data minimum retrieved. Returning +inf.");
462 this->Info("GetDataMin", "'dim' is between 0 and %d.", fDim - 1);
463 return std::numeric_limits<Double_t>::infinity();
464}
465
466/// Returns the maximum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1
468 if(dim < fDim)
469 return fDataThresholds[dim].second;
470 this->Warning("GetDataMax", "No such dimensional coordinate. No coordinate data maximum retrieved. Returning -inf.");
471 this->Info("GetDataMax", "'dim' is between 0 and %d.", fDim - 1);
472 return -1 * std::numeric_limits<Double_t>::infinity();
473}
474
475/// Returns the density in bin. 'bin' is between 0 and fNBins - 1
476/// The density is the bin content/ bin volume
478 if(bin < fNBins) {
479 Double_t volume = GetBinVolume(bin);
480 if (!volume)
481 this->Warning("GetBinDensity", "Volume is null. Returning -1.");
482 return GetBinContent(bin) / volume;
483 }
484 this->Warning("GetBinDensity", "No such bin. Returning -1.");
485 this->Info("GetBinDensity", "'bin' is between 0 and %d.", fNBins - 1);
486 return -1.;
487}
488
489/// Returns the (hyper)volume of bin. 'bin' is between 0 and fNBins - 1
491 if(bin < fNBins) {
492 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
493 Double_t volume = 1.;
494 for (UInt_t i = 0; i < fDim; ++i) {
495 volume *= (binEdges.second[i] - binEdges.first[i]);
496 }
497 return volume;
498 }
499 this->Warning("GetBinVolume", "No such bin. Returning 0.");
500 this->Info("GetBinVolume", "'bin' is between 0 and %d.", fNBins - 1);
501 return 0.;
502}
503
504/// Returns a pointer to the vector of the bin edges for one dimensional binning only.
505/// size of the vector is fNBins + 1 is the vector has been sorted in increasing bin edges
506/// N.B : if one does not call SortOneDimBinEdges the bins are not ordered
507const double * TKDTreeBinning::GetOneDimBinEdges() const {
508 if (fDim == 1) {
509 // no need to sort here because vector is already sorted in one dim
510 return &fBinMinEdges.front();
511 }
512 this->Warning("GetOneDimBinEdges", "Data is multidimensional. No sorted bin edges retrieved. Returning null pointer.");
513 this->Info("GetOneDimBinEdges", "This method can only be invoked if the data is a one dimensional set");
514 return nullptr;
515}
516
517/// Sort the one-dimensional bin edges and returns a pointer to them
519 if (fDim != 1) {
520 this->Warning("SortOneDimBinEdges", "Data is multidimensional. Cannot sorted bin edges. Returning null pointer.");
521 this->Info("SortOneDimBinEdges", "This method can only be invoked if the data is a one dimensional set");
522 return nullptr;
523 }
524 // order bins by increasing (or decreasing ) x positions
525 std::vector<UInt_t> indices(fNBins);
526 TMath::Sort( fNBins, &fBinMinEdges[0], &indices[0], !sortAsc );
527
528 std::vector<Double_t> binMinEdges(fNBins );
529 std::vector<Double_t> binMaxEdges(fNBins );
530 std::vector<UInt_t> binContent(fNBins ); // readjust also content (not needed but better in general!)
531 fIndices.resize( fNBins );
532 for (UInt_t i = 0; i < fNBins; ++i) {
533 binMinEdges[i ] = fBinMinEdges[indices[i] ];
534 binMaxEdges[i ] = fBinMaxEdges[indices[i] ];
535 binContent[i] = fBinsContent[indices[i] ];
536 fIndices[indices[i] ] = i; // for the inverse transformation
537 }
541
543
544 // Add also the upper(lower) edge to the min (max) list
545 if (sortAsc) {
546 fBinMinEdges.push_back(fBinMaxEdges.back());
548 return &fBinMinEdges[0];
549 }
550 fBinMaxEdges.push_back(fBinMinEdges.back());
551 return &fBinMaxEdges[0];
552
553}
554
555/// Returns the geometric center of of the bin. 'bin' is between 0 and fNBins - 1,
556/// Array must be deleted as "delete [] res"
558 if(bin < fNBins) {
560 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
561 for (UInt_t i = 0; i < fDim; ++i) {
562 result[i] = (binEdges.second[i] + binEdges.first[i]) / 2.;
563 }
564 return result;
565 }
566 this->Warning("GetBinCenter", "No such bin. Returning null pointer.");
567 this->Info("GetBinCenter", "'bin' is between 0 and %d.", fNBins - 1);
568 return nullptr;
569}
570
571/// Returns a pointer to the vector of the bin widths. 'bin' is between 0 and fNBins - 1
572/// Array must be deleted as "delete [] res"
574 if(bin < fNBins) {
576 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
577 for (UInt_t i = 0; i < fDim; ++i) {
578 result[i] = (binEdges.second[i] - binEdges.first[i]);
579 }
580 return result;
581 }
582 this->Warning("GetBinWidth", "No such bin. Returning null pointer.");
583 this->Info("GetBinWidth", "'bin' is between 0 and %d.", fNBins - 1);
584 return nullptr;
585}
586
587/// Return the bin with maximum density
589 if (fIsSorted) {
590 if (fIsSortedAsc)
591 return fNBins - 1;
592 else return 0;
593 }
594 UInt_t* indices = new UInt_t[fNBins];
595 for (UInt_t i = 0; i < fNBins; ++i)
596 indices[i] = i;
597 UInt_t result = *std::max_element(indices, indices + fNBins, CompareAsc(this));
598 delete [] indices;
599 return result;
600}
601
602/// Return the bin with minimum density
604 if (fIsSorted) {
605 if (!fIsSortedAsc)
606 return fNBins - 1;
607 else return 0;
608 }
609 UInt_t* indices = new UInt_t[fNBins];
610 for (UInt_t i = 0; i < fNBins; ++i)
611 indices[i] = i;
612 UInt_t result = *std::min_element(indices, indices + fNBins, CompareAsc(this));
613 delete [] indices;
614 return result;
615}
616
617/// Fill the bin data set (class ROOT::Fit::BinData) with the result of the TKDTree binning
619 if (!fDataBins) return;
620 data.Initialize(fNBins, fDim);
621 for (unsigned int i = 0; i < fNBins; ++i) {
622 data.Add( GetBinMinEdges(i), GetBinDensity(i), std::sqrt(double(GetBinContent(i) ))/ GetBinVolume(i) );
623 data.AddBinUpEdge(GetBinMaxEdges(i) );
624 }
625}
626
627/// find the corresponding bin index given the coordinate of a point
629
630 Int_t inode = fDataBins->FindNode(point);
631 // find node return the index in the total nodes and the bins are only the terminal ones
632 // so we subtract all the non-terminal nodes
633 inode -= fDataBins->GetNNodes();
634 R__ASSERT( inode >= 0);
635 UInt_t bin = inode;
636
637 if (!fIsSorted) return bin;
638 //return std::distance(fIndices.begin(), std::find(fIndices.begin(), fIndices.end(), bin ) );
639 return fIndices[bin];
640}
641
642/// Return the corresponding point belonging to the bin i
643std::vector<std::vector<Double_t> > TKDTreeBinning::GetPointsInBin(UInt_t bin) const {
644 std::vector<Double_t> point(fDim);
645 std::vector< std::vector<Double_t> > thePoints;
646 if (fData.empty()) {
647 Error("GetPointsInBin","Internal data set is not valid");
648 return thePoints;
649 }
650 if (!fDataBins) {
651 Error("GetPointsInBin","Internal TKDTree is not valid");
652 return thePoints;
653 }
654 if (bin >= fNBins) {
655 Error("GetPointsInBin","Invalid bin number");
656 return thePoints;
657 }
658 // need to find the bin number including the non-terminal node
659 int inode = bin + fDataBins->GetNNodes();
660 auto indices = fDataBins->GetPointsIndexes(inode);
661 int npoints = fDataBins->GetNPointsNode(inode);
662 thePoints.resize(npoints);
663 for (int ipoint = 0; ipoint < npoints; ++ipoint) {
664 for (unsigned int idim = 0; idim < fDim; ++idim) {
665 point[idim] = fData[idim*fDataSize+indices[ipoint] ];
666 }
667 thePoints[ipoint] = point;
668 }
669 return thePoints;
670}
671
672////////////////////////////////////////////////////////////////////////////////
673/// Stream a class object.
675 if (b.IsReading() ) {
677 Version_t v = b.ReadVersion(&R__s, &R__c);
678 b.ReadClassBuffer(TKDTreeBinning::Class(), this, v, R__s, R__c);
679 // we need to rebuild the TKDTree
680 if (fDataBins) delete fDataBins;
682 }
683 else {
684 // case of writing
685 b.WriteClassBuffer(TKDTreeBinning::Class(),this);
686 //std::cout << "writing npar = " << GetNpar() << std::endl;
687 }
688}
#define b(i)
Definition RSha256.hxx:100
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
TKDTree< Int_t, Double_t > TKDTreeID
Definition TKDTree.h:104
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition BinData.h:52
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A class providing multidimensional binning.
@ kAdjustBinEdges
adjust bin edges to avoid overlapping with data
std::vector< UInt_t > fBinsContent
Holds the contents of the bins.
UInt_t fNBins
The number of bins.
void ReadjustMinBinEdges(Double_t *binEdges)
TKDTreeBinning()
Default constructor (for I/O)
std::pair< const Double_t *, const Double_t * > GetBinsEdges() const
Returns a pair of an array with all bins minimum and maximum edges.
const Double_t * GetBinMaxEdges(UInt_t bin) const
Returns the bin's maximum edges. 'bin' is between 0 and fNBins - 1.
const Double_t * GetBinWidth(UInt_t bin) const
Returns a pointer to the vector of the bin widths.
const Double_t * GetBinsMaxEdges() const
Returns an array with all bins' maximum edges The edges are arranges as xmax_1,ymax_1,...
void SetCommonBinEdges(Double_t *binEdges)
const Double_t * GetBinCenter(UInt_t bin) const
Returns the geometric center of of the bin.
UInt_t GetBinMaxDensity() const
Return the bin with maximum density.
std::pair< const Double_t *, const Double_t * > GetBinEdges(UInt_t bin) const
Returns a pir with the bin's edges. 'bin' is between 0 and fNBins - 1.
UInt_t GetNBins() const
Returns the number of bins.
Bool_t fIsSorted
Flags if the bin edges are sorted densitywise (or by bin endges in case of 1-dim )
friend struct CompareAsc
! Predicate for ascending sort
~TKDTreeBinning() override
Class's destructor.
void SetData(Double_t *data)
void SetNBins(UInt_t bins)
Sets binning inner structure.
UInt_t fDataSize
The data size.
Double_t GetDataMax(UInt_t dim) const
Returns the maximum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1.
const Double_t * GetBinMinEdges(UInt_t bin) const
Returns the bin's minimum edges. 'bin' is between 0 and fNBins - 1.
Double_t GetDataMin(UInt_t dim) const
Returns the minimum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1.
UInt_t GetBinContent(UInt_t bin) const
Returns the number of points in bin. 'bin' is between 0 and fNBins - 1.
void FillBinData(ROOT::Fit::BinData &data) const
Fill the bin data set (class ROOT::Fit::BinData) with the result of the TKDTree binning.
std::vector< Double_t > fData
[fDataSize*fDim] The data from which a KDTree partition is computed for binning
Double_t GetBinVolume(UInt_t bin) const
Returns the (hyper)volume of bin. 'bin' is between 0 and fNBins - 1.
std::vector< std::pair< Double_t, Double_t > > fDataThresholds
Minimum and maximum data values.
void SortBinsByDensity(Bool_t sortAsc=kTRUE)
Sorts bins by their density.
std::vector< UInt_t > fIndices
Index of the bins in the kd-tree (needed when bins are sorted)
std::vector< Double_t > fBinMinEdges
The minimum values for the bins' edges for each dimension.
std::vector< Double_t > fBinMaxEdges
The maximum values for the bins' edges for each dimension.
void ReadjustMaxBinEdges(Double_t *binEdges)
std::vector< std::vector< std::pair< Bool_t, Bool_t > > > fCheckedBinEdges
! Auxiliary structure for readjusting the bin edges. Flags if the bin edge was processed in the algor...
UInt_t fDim
The data dimension.
void Streamer(TBuffer &) override
Stream a class object.
UInt_t FindBin(const Double_t *point) const
find the corresponding bin index given the coordinate of a point
Double_t GetBinDensity(UInt_t bin) const
Returns the density in bin.
TKDTreeID * fDataBins
! The binning inner structure.
Bool_t fIsSortedAsc
Flags if the bin edges are sorted densitywise (or by bin-edge for 1D) in ascending order.
static TClass * Class()
std::vector< std::vector< Double_t > > GetPointsInBin(UInt_t bin) const
Return the corresponding point belonging to the bin i.
std::vector< std::map< Double_t, std::vector< UInt_t > > > fCommonBinEdges
! Auxiliary structure for readjusting the bin edges. Keeps the common bin boundaries
const Double_t * GetBinsMinEdges() const
Returns an array with all bins' minimum edges The edges are arranges as xmin_1,ymin_1,...
void SetBinMinMaxEdges(Double_t *binEdges)
UInt_t GetBinMinDensity() const
Return the bin with minimum density.
const Double_t * GetOneDimBinEdges() const
Returns a pointer to the vector of the bin edges for one dimensional binning only.
const Double_t * GetDimData(UInt_t dim) const
UInt_t GetDim() const
Returns the number of dimensions.
TKDTreeID * GetTree() const
Returns the kD-Tree structure of the binning.
const Double_t * SortOneDimBinEdges(Bool_t sortAsc=kTRUE)
Sort the one-dimensional bin edges and returns a pointer to them.
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1072
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Sort the n elements of the array a of generic templated type Element.
Definition TMathBase.h:413
const TKDTreeBinning * bins
CompareAsc(const TKDTreeBinning *treebins)
Bool_t operator()(UInt_t bin1, UInt_t bin2)
const TKDTreeBinning * bins
Bool_t operator()(UInt_t bin1, UInt_t bin2)
CompareDesc(const TKDTreeBinning *treebins)