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 SetBinsEdges();
141 } else {
142 fDataBins = (TKDTreeID*)nullptr;
143 this->Warning("SetNBins", "Number of bins is bigger than data size. Nothing is built.");
144 }
145 } else {
146 fDataBins = (TKDTreeID*)nullptr;
147 if (!fDim)
148 this->Warning("SetNBins", "Data dimension is nil. Nothing is built.");
149 if (!fNBins)
150 this->Warning("SetNBins", "Number of bins is nil. Nothing is built.");
151 if (!fDataSize)
152 this->Warning("SetNBins", "Data size is nil. Nothing is built.");
153 }
154}
155
156/// Sorts bins by their density
158 if (fDim == 1) {
159 // in one dim they are already sorted (no need to do anything)
160 return;
161 } else {
162 std::vector<UInt_t> indices(fNBins); // vector for indices (for the inverse transformation)
163 for (UInt_t i = 0; i < fNBins; ++i)
164 indices[i] = i;
165 if (sortAsc) {
166 std::sort(indices.begin(), indices.end(), CompareAsc(this));
168 } else {
169 std::sort(indices.begin(), indices.end(), CompareDesc(this));
171 }
172 std::vector<Double_t> binMinEdges(fNBins * fDim);
173 std::vector<Double_t> binMaxEdges(fNBins * fDim);
174 std::vector<UInt_t> binContent(fNBins ); // readjust also content (not needed but better in general!)
175 fIndices.resize(fNBins);
176 for (UInt_t i = 0; i < fNBins; ++i) {
177 for (UInt_t j = 0; j < fDim; ++j) {
178 binMinEdges[i * fDim + j] = fBinMinEdges[indices[i] * fDim + j];
179 binMaxEdges[i * fDim + j] = fBinMaxEdges[indices[i] * fDim + j];
180 }
181 binContent[i] = fBinsContent[indices[i]];
182 fIndices[indices[i]] = i;
183 }
187
188 // not needed anymore if readjusting bin content all the time
189 // re-adjust content of extra bins if exists
190 // since it is different than the others
191 // if ( fDataSize % fNBins != 0) {
192 // UInt_t k = 0;
193 // Bool_t found = kFALSE;
194 // while (!found) {
195 // if (indices[k] == fNBins - 1) {
196 // found = kTRUE;
197 // break;
198 // }
199 // ++k;
200 // }
201 // fBinsContent[fNBins - 1] = fDataBins->GetBucketSize();
202 // fBinsContent[k] = fDataSize % fNBins-1;
203 // }
204
206 }
207}
208
210 // Sets the data and finds minimum and maximum by dimensional coordinate
211 fData.resize(fDim*fDataSize);
212 auto first = fData.begin();
213 for (UInt_t i = 0; i < fDim; ++i) {
214 for (UInt_t j = 0; j < fDataSize; ++j) {
215 fData[i*fDataSize+j] = data[i * fDataSize + j];
216 }
217 auto end = first+fDataSize;
218 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
219 first = end;
220 }
221}
222void TKDTreeBinning::SetData(const std::vector<double>& data) {
223 // Sets the data and finds minimum and maximum by dimensional coordinate
224 fData = data;
225 auto first = fData.begin();
226 // find min/max
227 for (UInt_t i = 0; i < fDim; ++i) {
228 auto end = first+fDataSize;
229 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
230 first = end;
231 }
232}
233
235 // Sets the data for constructing the kD-tree
236 for (UInt_t i = 0; i < fDim; ++i)
237 fDataBins->SetData(i, &fData[i*fDataSize]);
238}
239
241 // Sets the bins' content
242 fBinsContent.resize(fNBins);
243 for (UInt_t i = 0; i < fNBins; ++i)
244 fBinsContent[i] = fDataBins->GetBucketSize();
245 if ( fDataSize % fNBins != 0 )
246 fBinsContent[fNBins - 1] = fDataSize % (fNBins-1);
247}
248
250 // Sets the bins' edges
251 //Double_t* rawBinEdges = fDataBins->GetBoundaryExact(fDataBins->GetNNodes());
252 Double_t* rawBinEdges = fDataBins->GetBoundary(fDataBins->GetNNodes());
253 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)));
254 fCommonBinEdges = std::vector<std::map<Double_t, std::vector<UInt_t> > >(fDim, std::map<Double_t, std::vector<UInt_t> >());
256 if (TestBit(kAdjustBinEdges) ) {
259 }
261 fCommonBinEdges.clear();
262 fCheckedBinEdges.clear();
263}
264
266 // Sets the bins' minimum and maximum edges
267 fBinMinEdges.reserve(fNBins * fDim);
268 fBinMaxEdges.reserve(fNBins * fDim);
269 for (UInt_t i = 0; i < fNBins; ++i) {
270 for (UInt_t j = 0; j < fDim; ++j) {
271 fBinMinEdges.push_back(binEdges[(i * fDim + j) * 2]);
272 fBinMaxEdges.push_back(binEdges[(i * fDim + j) * 2 + 1]);
273 }
274 }
275}
276
278 // Sets indexing on the bin edges which have common boundaries
279 for (UInt_t i = 0; i < fDim; ++i) {
280 for (UInt_t j = 0; j < fNBins; ++j) {
281 Double_t binEdge = binEdges[(j * fDim + i) * 2];
282 if(fCommonBinEdges[i].find(binEdge) == fCommonBinEdges[i].end()) {
283 std::vector<UInt_t> commonBinEdges;
284 for (UInt_t k = 0; k < fNBins; ++k) {
285 UInt_t minBinEdgePos = (k * fDim + i) * 2;
286 if (std::fabs(binEdge - binEdges[minBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
287 commonBinEdges.push_back(minBinEdgePos);
289 if (std::fabs(binEdge - binEdges[maxBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
290 commonBinEdges.push_back(maxBinEdgePos);
291 }
293 }
294 }
295 }
296}
297
299 // Readjusts the bins' minimum edge by shifting it slightly lower
300 // to avoid overlapping with the data
301 for (UInt_t i = 0; i < fDim; ++i) {
302 for (UInt_t j = 0; j < fNBins; ++j) {
303 if (!fCheckedBinEdges[i][j].first) {
304 Double_t binEdge = binEdges[(j * fDim + i) * 2];
306 double eps = -10*std::numeric_limits<Double_t>::epsilon();
307 if (adjustedBinEdge != 0)
308 adjustedBinEdge *= (1. + eps);
309 else
310 adjustedBinEdge += eps;
311
312 for (UInt_t k = 0; k < fCommonBinEdges[i][binEdge].size(); ++k) {
314 Bool_t isMinBinEdge = binEdgePos % 2 == 0;
315 UInt_t bin = isMinBinEdge ? (binEdgePos / 2 - i) / fDim : ((binEdgePos - 1) / 2 - i) / fDim;
316 binEdges[binEdgePos] = adjustedBinEdge;
317 if (isMinBinEdge)
318 fCheckedBinEdges[i][bin].first = kTRUE;
319 else
320 fCheckedBinEdges[i][bin].second = kTRUE;
321 }
322 }
323 }
324 }
325}
326
328 // Readjusts the bins' maximum edge
329 // and shift it slightly higher
330 for (UInt_t i = 0; i < fDim; ++i) {
331 for (UInt_t j = 0; j < fNBins; ++j) {
332 if (!fCheckedBinEdges[i][j].second) {
333 Double_t& binEdge = binEdges[(j * fDim + i) * 2 + 1];
334 double eps = 10*std::numeric_limits<Double_t>::epsilon();
335 if (binEdge != 0)
336 binEdge *= (1. + eps);
337 else
338 binEdge += eps;
339
340
341 }
342 }
343 }
344}
345
346/// Returns an array with all bins' minimum edges
347/// The edges are arranges as xmin_1,ymin_1, xmin_2,ymin_2,....xmin_{nbin},ymin_{nbin}
349 if (fDataBins)
350 return &fBinMinEdges[0];
351 this->Warning("GetBinsMinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
352 this->Info("GetBinsMinEdges", "Returning null pointer.");
353 return (Double_t*)nullptr;
354}
355
356/// Returns an array with all bins' maximum edges
357/// The edges are arranges as xmax_1,ymax_1, xmax_2,ymax_2,....xmax_{nbin},ymax_{nbin}
359 // Returns the bins' maximum edges
360 if (fDataBins)
361 return &fBinMaxEdges[0];
362 this->Warning("GetBinsMaxEdges", "Binning kd-tree is nil. No bin edges retrieved.");
363 this->Info("GetBinsMaxEdges", "Returning null pointer.");
364 return (Double_t*)nullptr;
365}
366
367/// Returns a pair of an array with all bins minimum and maximum edges
368std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinsEdges() const {
369 // Returns the bins' edges
370 if (fDataBins)
371 return std::make_pair(GetBinsMinEdges(), GetBinsMaxEdges());
372 this->Warning("GetBinsEdges", "Binning kd-tree is nil. No bin edges retrieved.");
373 this->Info("GetBinsEdges", "Returning null pointer pair.");
374 return std::make_pair((Double_t*)nullptr, (Double_t*)nullptr);
375}
376
377/// Returns the bin's minimum edges. 'bin' is between 0 and fNBins - 1
379 if (fDataBins)
380 if (bin < fNBins)
381 return &fBinMinEdges[bin * fDim];
382 else
383 this->Warning("GetBinMinEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
384 else
385 this->Warning("GetBinMinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
386 this->Info("GetBinMinEdges", "Returning null pointer.");
387 return (Double_t*)nullptr;
388}
389
390/// Returns the bin's maximum edges. 'bin' is between 0 and fNBins - 1
392 if (fDataBins)
393 if (bin < fNBins)
394 return &fBinMaxEdges[bin * fDim];
395 else
396 this->Warning("GetBinMaxEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
397 else
398 this->Warning("GetBinMaxEdges", "Binning kd-tree is nil. No bin edges retrieved.");
399 this->Info("GetBinMaxEdges", "Returning null pointer.");
400 return (Double_t*)nullptr;
401}
402
403/// Returns a pir with the bin's edges. 'bin' is between 0 and fNBins - 1
404std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinEdges(UInt_t bin) const {
405 if (fDataBins)
406 if (bin < fNBins)
407 return std::make_pair(GetBinMinEdges(bin), GetBinMaxEdges(bin));
408 else
409 this->Warning("GetBinEdges", "No such bin. 'bin' is between 0 and %d", fNBins - 1);
410 else
411 this->Warning("GetBinEdges", "Binning kd-tree is nil. No bin edges retrieved.");
412 this->Info("GetBinEdges", "Returning null pointer pair.");
413 return std::make_pair((Double_t*)nullptr, (Double_t*)nullptr);
414}
415
416/// Returns the number of bins
418 return fNBins;
419}
420
421/// Returns the number of dimensions
423 return fDim;
424}
425
426/// Returns the number of points in bin. 'bin' is between 0 and fNBins - 1
428 if(bin <= fNBins - 1)
429 return fBinsContent[bin];
430 this->Warning("GetBinContent", "No such bin. Returning 0.");
431 this->Info("GetBinContent", "'bin' is between 0 and %d.", fNBins - 1);
432 return 0;
433}
434
435
436/// Returns the kD-Tree structure of the binning
438 if (fDataBins)
439 return fDataBins;
440 this->Warning("GetTree", "Binning kd-tree is nil. No embedded kd-tree retrieved. Returning null pointer.");
441 return (TKDTreeID*)nullptr;
442}
443
444// Returns the data array in the dim coordinate. 'dim' is between 0 and fDim - 1
446 if(dim < fDim)
447 return &fData[dim*fDataSize];
448 this->Warning("GetDimData", "No such dimensional coordinate. No coordinate data retrieved. Returning null pointer.");
449 this->Info("GetDimData", "'dim' is between 0 and %d.", fDim - 1);
450 return nullptr;
451}
452
453/// Returns the minimum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1
455 if(dim < fDim)
456 return fDataThresholds[dim].first;
457 this->Warning("GetDataMin", "No such dimensional coordinate. No coordinate data minimum retrieved. Returning +inf.");
458 this->Info("GetDataMin", "'dim' is between 0 and %d.", fDim - 1);
459 return std::numeric_limits<Double_t>::infinity();
460}
461
462/// Returns the maximum of the data in the dim coordinate. 'dim' is between 0 and fDim - 1
464 if(dim < fDim)
465 return fDataThresholds[dim].second;
466 this->Warning("GetDataMax", "No such dimensional coordinate. No coordinate data maximum retrieved. Returning -inf.");
467 this->Info("GetDataMax", "'dim' is between 0 and %d.", fDim - 1);
468 return -1 * std::numeric_limits<Double_t>::infinity();
469}
470
471/// Returns the density in bin. 'bin' is between 0 and fNBins - 1
472/// The density is the bin content/ bin volume
474 if(bin < fNBins) {
475 Double_t volume = GetBinVolume(bin);
476 if (!volume)
477 this->Warning("GetBinDensity", "Volume is null. Returning -1.");
478 return GetBinContent(bin) / volume;
479 }
480 this->Warning("GetBinDensity", "No such bin. Returning -1.");
481 this->Info("GetBinDensity", "'bin' is between 0 and %d.", fNBins - 1);
482 return -1.;
483}
484
485/// Returns the (hyper)volume of bin. 'bin' is between 0 and fNBins - 1
487 if(bin < fNBins) {
488 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
489 Double_t volume = 1.;
490 for (UInt_t i = 0; i < fDim; ++i) {
491 volume *= (binEdges.second[i] - binEdges.first[i]);
492 }
493 return volume;
494 }
495 this->Warning("GetBinVolume", "No such bin. Returning 0.");
496 this->Info("GetBinVolume", "'bin' is between 0 and %d.", fNBins - 1);
497 return 0.;
498}
499
500/// Returns a pointer to the vector of the bin edges for one dimensional binning only.
501/// size of the vector is fNBins + 1 is the vector has been sorted in increasing bin edges
502/// N.B : if one does not call SortOneDimBinEdges the bins are not ordered
503const double * TKDTreeBinning::GetOneDimBinEdges() const {
504 if (fDim == 1) {
505 // no need to sort here because vector is already sorted in one dim
506 return &fBinMinEdges.front();
507 }
508 this->Warning("GetOneDimBinEdges", "Data is multidimensional. No sorted bin edges retrieved. Returning null pointer.");
509 this->Info("GetOneDimBinEdges", "This method can only be invoked if the data is a one dimensional set");
510 return nullptr;
511}
512
513/// Sort the one-dimensional bin edges and returns a pointer to them
515 if (fDim != 1) {
516 this->Warning("SortOneDimBinEdges", "Data is multidimensional. Cannot sorted bin edges. Returning null pointer.");
517 this->Info("SortOneDimBinEdges", "This method can only be invoked if the data is a one dimensional set");
518 return nullptr;
519 }
520 // order bins by increasing (or decreasing ) x positions
521 std::vector<UInt_t> indices(fNBins);
522 TMath::Sort( fNBins, &fBinMinEdges[0], &indices[0], !sortAsc );
523
524 std::vector<Double_t> binMinEdges(fNBins );
525 std::vector<Double_t> binMaxEdges(fNBins );
526 std::vector<UInt_t> binContent(fNBins ); // readjust also content (not needed but better in general!)
527 fIndices.resize( fNBins );
528 for (UInt_t i = 0; i < fNBins; ++i) {
529 binMinEdges[i ] = fBinMinEdges[indices[i] ];
530 binMaxEdges[i ] = fBinMaxEdges[indices[i] ];
531 binContent[i] = fBinsContent[indices[i] ];
532 fIndices[indices[i] ] = i; // for the inverse transformation
533 }
537
539
540 // Add also the upper(lower) edge to the min (max) list
541 if (sortAsc) {
542 fBinMinEdges.push_back(fBinMaxEdges.back());
544 return &fBinMinEdges[0];
545 }
546 fBinMaxEdges.push_back(fBinMinEdges.back());
547 return &fBinMaxEdges[0];
548
549}
550
551/// Returns the geometric center of of the bin. 'bin' is between 0 and fNBins - 1,
552/// Array must be deleted as "delete [] res"
554 if(bin < fNBins) {
556 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
557 for (UInt_t i = 0; i < fDim; ++i) {
558 result[i] = (binEdges.second[i] + binEdges.first[i]) / 2.;
559 }
560 return result;
561 }
562 this->Warning("GetBinCenter", "No such bin. Returning null pointer.");
563 this->Info("GetBinCenter", "'bin' is between 0 and %d.", fNBins - 1);
564 return nullptr;
565}
566
567/// Returns a pointer to the vector of the bin widths. 'bin' is between 0 and fNBins - 1
568/// Array must be deleted as "delete [] res"
570 if(bin < fNBins) {
572 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
573 for (UInt_t i = 0; i < fDim; ++i) {
574 result[i] = (binEdges.second[i] - binEdges.first[i]);
575 }
576 return result;
577 }
578 this->Warning("GetBinWidth", "No such bin. Returning null pointer.");
579 this->Info("GetBinWidth", "'bin' is between 0 and %d.", fNBins - 1);
580 return nullptr;
581}
582
583/// Return the bin with maximum density
585 if (fIsSorted) {
586 if (fIsSortedAsc)
587 return fNBins - 1;
588 else return 0;
589 }
590 UInt_t* indices = new UInt_t[fNBins];
591 for (UInt_t i = 0; i < fNBins; ++i)
592 indices[i] = i;
593 UInt_t result = *std::max_element(indices, indices + fNBins, CompareAsc(this));
594 delete [] indices;
595 return result;
596}
597
598/// Return the bin with minimum density
600 if (fIsSorted) {
601 if (!fIsSortedAsc)
602 return fNBins - 1;
603 else return 0;
604 }
605 UInt_t* indices = new UInt_t[fNBins];
606 for (UInt_t i = 0; i < fNBins; ++i)
607 indices[i] = i;
608 UInt_t result = *std::min_element(indices, indices + fNBins, CompareAsc(this));
609 delete [] indices;
610 return result;
611}
612
613/// Fill the bin data set (class ROOT::Fit::BinData) with the result of the TKDTree binning
615 if (!fDataBins) return;
616 data.Initialize(fNBins, fDim);
617 for (unsigned int i = 0; i < fNBins; ++i) {
618 data.Add( GetBinMinEdges(i), GetBinDensity(i), std::sqrt(double(GetBinContent(i) ))/ GetBinVolume(i) );
619 data.AddBinUpEdge(GetBinMaxEdges(i) );
620 }
621}
622
623/// find the corresponding bin index given the coordinate of a point
625
626 Int_t inode = fDataBins->FindNode(point);
627 // find node return the index in the total nodes and the bins are only the terminal ones
628 // so we subtract all the non-terminal nodes
629 inode -= fDataBins->GetNNodes();
630 R__ASSERT( inode >= 0);
631 UInt_t bin = inode;
632
633 if (!fIsSorted) return bin;
634 //return std::distance(fIndices.begin(), std::find(fIndices.begin(), fIndices.end(), bin ) );
635 return fIndices[bin];
636}
637
638/// Return the corresponding point belonging to the bin i
639std::vector<std::vector<Double_t> > TKDTreeBinning::GetPointsInBin(UInt_t bin) const {
640 std::vector<Double_t> point(fDim);
641 std::vector< std::vector<Double_t> > thePoints;
642 if (fData.empty()) {
643 Error("GetPointsInBin","Internal data set is not valid");
644 return thePoints;
645 }
646 if (!fDataBins) {
647 Error("GetPointsInBin","Internal TKDTree is not valid");
648 return thePoints;
649 }
650 if (bin >= fNBins) {
651 Error("GetPointsInBin","Invalid bin number");
652 return thePoints;
653 }
654 // need to find the bin number including the non-terminal node
655 int inode = bin + fDataBins->GetNNodes();
656 auto indices = fDataBins->GetPointsIndexes(inode);
657 int npoints = fDataBins->GetNPointsNode(inode);
658 thePoints.resize(npoints);
659 for (int ipoint = 0; ipoint < npoints; ++ipoint) {
660 for (unsigned int idim = 0; idim < fDim; ++idim) {
661 point[idim] = fData[idim*fDataSize+indices[ipoint] ];
662 }
663 thePoints[ipoint] = point;
664 }
665 return thePoints;
666}
667
668////////////////////////////////////////////////////////////////////////////////
669/// Stream a class object.
671 if (b.IsReading() ) {
673 Version_t v = b.ReadVersion(&R__s, &R__c);
674 b.ReadClassBuffer(TKDTreeBinning::Class(), this, v, R__s, R__c);
675 // we need to rebuild the TKDTree
676 if (fDataBins) delete fDataBins;
678 }
679 else {
680 // case of writing
681 b.WriteClassBuffer(TKDTreeBinning::Class(),this);
682 //std::cout << "writing npar = " << GetNpar() << std::endl;
683 }
684}
#define b(i)
Definition RSha256.hxx:100
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
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.
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...
@ kAdjustBinEdges
adjust bin edges to avoid overlapping with data
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:202
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
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:432
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)