24 ClassImp(TKDTreeBinning);
46 struct TKDTreeBinning::CompareAsc {
48 CompareAsc(
const TKDTreeBinning* treebins) : bins(treebins) {}
49 Bool_t operator()(UInt_t bin1, UInt_t bin2) {
50 return bins->GetBinDensity(bin1) < bins->GetBinDensity(bin2);
52 const TKDTreeBinning* bins;
55 struct TKDTreeBinning::CompareDesc {
57 CompareDesc(
const TKDTreeBinning* treebins) : bins(treebins) {}
58 Bool_t operator()(UInt_t bin1, UInt_t bin2) {
59 return bins->GetBinDensity(bin1) > bins->GetBinDensity(bin2);
61 const TKDTreeBinning* bins;
74 TKDTreeBinning::TKDTreeBinning(UInt_t dataSize, UInt_t dataDim, Double_t* data, UInt_t nBins,
bool adjustBinEdges)
75 : fData(0), fBinMinEdges(std::vector<Double_t>()), fBinMaxEdges(std::vector<Double_t>()), fDataBins((TKDTreeID*)0), fDim(dataDim),
76 fDataSize(dataSize), fDataThresholds(std::vector<std::pair<Double_t, Double_t> >(fDim, std::make_pair(0., 0.))),
77 fIsSorted(kFALSE), fIsSortedAsc(kFALSE), fBinsContent(std::vector<UInt_t>()) {
78 if (adjustBinEdges) SetBit(kAdjustBinEdges);
84 this->Warning(
"TKDTreeBinning",
"Data is nil. Nothing is built.");
98 TKDTreeBinning::TKDTreeBinning(UInt_t dataSize, UInt_t dataDim,
const std::vector<double> &data, UInt_t nBins,
bool adjustBinEdges)
99 : fData(0), fBinMinEdges(std::vector<Double_t>()), fBinMaxEdges(std::vector<Double_t>()), fDataBins((TKDTreeID*)0), fNBins (nBins), fDim(dataDim),
100 fDataSize(dataSize), fDataThresholds(std::vector<std::pair<Double_t, Double_t> >(fDim, std::make_pair(0., 0.))),
101 fIsSorted(kFALSE), fIsSortedAsc(kFALSE), fBinsContent(std::vector<UInt_t>()) {
102 if (adjustBinEdges) SetBit(kAdjustBinEdges);
108 this->Warning(
"TKDTreeBinning",
"Data is nil. Nothing is built.");
113 TKDTreeBinning::TKDTreeBinning() :
119 fIsSorted(kFALSE), fIsSortedAsc(kFALSE)
123 TKDTreeBinning::~TKDTreeBinning() {
125 if (fDataBins)
delete fDataBins;
129 void TKDTreeBinning::SetNBins(UInt_t bins) {
131 if (fDim && fNBins && fDataSize) {
132 if (fDataSize / fNBins) {
133 Bool_t remainingData = fDataSize % fNBins;
136 this->Info(
"SetNBins",
"Number of bins is not enough to hold the data. Extra bin added.");
138 fDataBins =
new TKDTreeID(fDataSize, fDim, fDataSize / (fNBins - remainingData));
144 fDataBins = (TKDTreeID*)0;
145 this->Warning(
"SetNBins",
"Number of bins is bigger than data size. Nothing is built.");
148 fDataBins = (TKDTreeID*)0;
150 this->Warning(
"SetNBins",
"Data dimension is nil. Nothing is built.");
152 this->Warning(
"SetNBins",
"Number of bins is nil. Nothing is built.");
154 this->Warning(
"SetNBins",
"Data size is nil. Nothing is built.");
159 void TKDTreeBinning::SortBinsByDensity(Bool_t sortAsc) {
164 std::vector<UInt_t> indices(fNBins);
165 for (UInt_t i = 0; i < fNBins; ++i)
168 std::sort(indices.begin(), indices.end(), CompareAsc(
this));
169 fIsSortedAsc = kTRUE;
171 std::sort(indices.begin(), indices.end(), CompareDesc(
this));
172 fIsSortedAsc = kFALSE;
174 std::vector<Double_t> binMinEdges(fNBins * fDim);
175 std::vector<Double_t> binMaxEdges(fNBins * fDim);
176 std::vector<UInt_t> binContent(fNBins );
177 fIndices.resize(fNBins);
178 for (UInt_t i = 0; i < fNBins; ++i) {
179 for (UInt_t j = 0; j < fDim; ++j) {
180 binMinEdges[i * fDim + j] = fBinMinEdges[indices[i] * fDim + j];
181 binMaxEdges[i * fDim + j] = fBinMaxEdges[indices[i] * fDim + j];
183 binContent[i] = fBinsContent[indices[i]];
184 fIndices[indices[i]] = i;
186 fBinMinEdges.swap(binMinEdges);
187 fBinMaxEdges.swap(binMaxEdges);
188 fBinsContent.swap(binContent);
211 void TKDTreeBinning::SetData(Double_t* data) {
213 fData.resize(fDim*fDataSize);
214 auto first = fData.begin();
215 for (UInt_t i = 0; i < fDim; ++i) {
216 for (UInt_t j = 0; j < fDataSize; ++j) {
217 fData[i*fDataSize+j] = data[i * fDataSize + j];
219 auto end = first+fDataSize;
220 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
224 void TKDTreeBinning::SetData(
const std::vector<double>& data) {
227 auto first = fData.begin();
229 for (UInt_t i = 0; i < fDim; ++i) {
230 auto end = first+fDataSize;
231 fDataThresholds[i] = std::make_pair(*std::min_element(first, end), *std::max_element(first,end));
236 void TKDTreeBinning::SetTreeData() {
238 for (UInt_t i = 0; i < fDim; ++i)
239 fDataBins->SetData(i, &fData[i*fDataSize]);
242 void TKDTreeBinning::SetBinsContent() {
244 fBinsContent.resize(fNBins);
245 for (UInt_t i = 0; i < fNBins; ++i)
246 fBinsContent[i] = fDataBins->GetBucketSize();
247 if ( fDataSize % fNBins != 0 )
248 fBinsContent[fNBins - 1] = fDataSize % (fNBins-1);
251 void TKDTreeBinning::SetBinsEdges() {
254 Double_t* rawBinEdges = fDataBins->GetBoundary(fDataBins->GetNNodes());
255 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)));
256 fCommonBinEdges = std::vector<std::map<Double_t, std::vector<UInt_t> > >(fDim, std::map<Double_t, std::vector<UInt_t> >());
257 SetCommonBinEdges(rawBinEdges);
258 if (TestBit(kAdjustBinEdges) ) {
259 ReadjustMinBinEdges(rawBinEdges);
260 ReadjustMaxBinEdges(rawBinEdges);
262 SetBinMinMaxEdges(rawBinEdges);
263 fCommonBinEdges.clear();
264 fCheckedBinEdges.clear();
267 void TKDTreeBinning::SetBinMinMaxEdges(Double_t* binEdges) {
269 fBinMinEdges.reserve(fNBins * fDim);
270 fBinMaxEdges.reserve(fNBins * fDim);
271 for (UInt_t i = 0; i < fNBins; ++i) {
272 for (UInt_t j = 0; j < fDim; ++j) {
273 fBinMinEdges.push_back(binEdges[(i * fDim + j) * 2]);
274 fBinMaxEdges.push_back(binEdges[(i * fDim + j) * 2 + 1]);
279 void TKDTreeBinning::SetCommonBinEdges(Double_t* binEdges) {
281 for (UInt_t i = 0; i < fDim; ++i) {
282 for (UInt_t j = 0; j < fNBins; ++j) {
283 Double_t binEdge = binEdges[(j * fDim + i) * 2];
284 if(fCommonBinEdges[i].find(binEdge) == fCommonBinEdges[i].end()) {
285 std::vector<UInt_t> commonBinEdges;
286 for (UInt_t k = 0; k < fNBins; ++k) {
287 UInt_t minBinEdgePos = (k * fDim + i) * 2;
288 if (std::fabs(binEdge - binEdges[minBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
289 commonBinEdges.push_back(minBinEdgePos);
290 UInt_t maxBinEdgePos = ++minBinEdgePos;
291 if (std::fabs(binEdge - binEdges[maxBinEdgePos]) < std::numeric_limits<Double_t>::epsilon())
292 commonBinEdges.push_back(maxBinEdgePos);
294 fCommonBinEdges[i][binEdge] = commonBinEdges;
300 void TKDTreeBinning::ReadjustMinBinEdges(Double_t* binEdges) {
303 for (UInt_t i = 0; i < fDim; ++i) {
304 for (UInt_t j = 0; j < fNBins; ++j) {
305 if (!fCheckedBinEdges[i][j].first) {
306 Double_t binEdge = binEdges[(j * fDim + i) * 2];
307 Double_t adjustedBinEdge = binEdge;
308 double eps = -10*std::numeric_limits<Double_t>::epsilon();
309 if (adjustedBinEdge != 0)
310 adjustedBinEdge *= (1. + eps);
312 adjustedBinEdge += eps;
314 for (UInt_t k = 0; k < fCommonBinEdges[i][binEdge].size(); ++k) {
315 UInt_t binEdgePos = fCommonBinEdges[i][binEdge][k];
316 Bool_t isMinBinEdge = binEdgePos % 2 == 0;
317 UInt_t bin = isMinBinEdge ? (binEdgePos / 2 - i) / fDim : ((binEdgePos - 1) / 2 - i) / fDim;
318 binEdges[binEdgePos] = adjustedBinEdge;
320 fCheckedBinEdges[i][bin].first = kTRUE;
322 fCheckedBinEdges[i][bin].second = kTRUE;
329 void TKDTreeBinning::ReadjustMaxBinEdges(Double_t* binEdges) {
332 for (UInt_t i = 0; i < fDim; ++i) {
333 for (UInt_t j = 0; j < fNBins; ++j) {
334 if (!fCheckedBinEdges[i][j].second) {
335 Double_t& binEdge = binEdges[(j * fDim + i) * 2 + 1];
336 double eps = 10*std::numeric_limits<Double_t>::epsilon();
338 binEdge *= (1. + eps);
350 const Double_t* TKDTreeBinning::GetBinsMinEdges()
const {
352 return &fBinMinEdges[0];
353 this->Warning(
"GetBinsMinEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
354 this->Info(
"GetBinsMinEdges",
"Returning null pointer.");
360 const Double_t* TKDTreeBinning::GetBinsMaxEdges()
const {
363 return &fBinMaxEdges[0];
364 this->Warning(
"GetBinsMaxEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
365 this->Info(
"GetBinsMaxEdges",
"Returning null pointer.");
370 std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinsEdges()
const {
373 return std::make_pair(GetBinsMinEdges(), GetBinsMaxEdges());
374 this->Warning(
"GetBinsEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
375 this->Info(
"GetBinsEdges",
"Returning null pointer pair.");
376 return std::make_pair((Double_t*)0, (Double_t*)0);
380 const Double_t* TKDTreeBinning::GetBinMinEdges(UInt_t bin)
const {
383 return &fBinMinEdges[bin * fDim];
385 this->Warning(
"GetBinMinEdges",
"No such bin. 'bin' is between 0 and %d", fNBins - 1);
387 this->Warning(
"GetBinMinEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
388 this->Info(
"GetBinMinEdges",
"Returning null pointer.");
393 const Double_t* TKDTreeBinning::GetBinMaxEdges(UInt_t bin)
const {
396 return &fBinMaxEdges[bin * fDim];
398 this->Warning(
"GetBinMaxEdges",
"No such bin. 'bin' is between 0 and %d", fNBins - 1);
400 this->Warning(
"GetBinMaxEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
401 this->Info(
"GetBinMaxEdges",
"Returning null pointer.");
406 std::pair<const Double_t*, const Double_t*> TKDTreeBinning::GetBinEdges(UInt_t bin)
const {
409 return std::make_pair(GetBinMinEdges(bin), GetBinMaxEdges(bin));
411 this->Warning(
"GetBinEdges",
"No such bin. 'bin' is between 0 and %d", fNBins - 1);
413 this->Warning(
"GetBinEdges",
"Binning kd-tree is nil. No bin edges retrieved.");
414 this->Info(
"GetBinEdges",
"Returning null pointer pair.");
415 return std::make_pair((Double_t*)0, (Double_t*)0);
419 UInt_t TKDTreeBinning::GetNBins()
const {
424 UInt_t TKDTreeBinning::GetDim()
const {
429 UInt_t TKDTreeBinning::GetBinContent(UInt_t bin)
const {
430 if(bin <= fNBins - 1)
431 return fBinsContent[bin];
432 this->Warning(
"GetBinContent",
"No such bin. Returning 0.");
433 this->Info(
"GetBinContent",
"'bin' is between 0 and %d.", fNBins - 1);
439 TKDTreeID* TKDTreeBinning::GetTree()
const {
442 this->Warning(
"GetTree",
"Binning kd-tree is nil. No embedded kd-tree retrieved. Returning null pointer.");
443 return (TKDTreeID*)0;
447 const Double_t* TKDTreeBinning::GetDimData(UInt_t dim)
const {
449 return &fData[dim*fDataSize];
450 this->Warning(
"GetDimData",
"No such dimensional coordinate. No coordinate data retrieved. Returning null pointer.");
451 this->Info(
"GetDimData",
"'dim' is between 0 and %d.", fDim - 1);
456 Double_t TKDTreeBinning::GetDataMin(UInt_t dim)
const {
458 return fDataThresholds[dim].first;
459 this->Warning(
"GetDataMin",
"No such dimensional coordinate. No coordinate data minimum retrieved. Returning +inf.");
460 this->Info(
"GetDataMin",
"'dim' is between 0 and %d.", fDim - 1);
461 return std::numeric_limits<Double_t>::infinity();
465 Double_t TKDTreeBinning::GetDataMax(UInt_t dim)
const {
467 return fDataThresholds[dim].second;
468 this->Warning(
"GetDataMax",
"No such dimensional coordinate. No coordinate data maximum retrieved. Returning -inf.");
469 this->Info(
"GetDataMax",
"'dim' is between 0 and %d.", fDim - 1);
470 return -1 * std::numeric_limits<Double_t>::infinity();
475 Double_t TKDTreeBinning::GetBinDensity(UInt_t bin)
const {
477 Double_t volume = GetBinVolume(bin);
479 this->Warning(
"GetBinDensity",
"Volume is null. Returning -1.");
480 return GetBinContent(bin) / volume;
482 this->Warning(
"GetBinDensity",
"No such bin. Returning -1.");
483 this->Info(
"GetBinDensity",
"'bin' is between 0 and %d.", fNBins - 1);
488 Double_t TKDTreeBinning::GetBinVolume(UInt_t bin)
const {
490 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
491 Double_t volume = 1.;
492 for (UInt_t i = 0; i < fDim; ++i) {
493 volume *= (binEdges.second[i] - binEdges.first[i]);
497 this->Warning(
"GetBinVolume",
"No such bin. Returning 0.");
498 this->Info(
"GetBinVolume",
"'bin' is between 0 and %d.", fNBins - 1);
505 const double * TKDTreeBinning::GetOneDimBinEdges()
const {
508 return &fBinMinEdges.front();
510 this->Warning(
"GetOneDimBinEdges",
"Data is multidimensional. No sorted bin edges retrieved. Returning null pointer.");
511 this->Info(
"GetOneDimBinEdges",
"This method can only be invoked if the data is a one dimensional set");
516 const Double_t * TKDTreeBinning::SortOneDimBinEdges(Bool_t sortAsc) {
518 this->Warning(
"SortOneDimBinEdges",
"Data is multidimensional. Cannot sorted bin edges. Returning null pointer.");
519 this->Info(
"SortOneDimBinEdges",
"This method can only be invoked if the data is a one dimensional set");
523 std::vector<UInt_t> indices(fNBins);
524 TMath::Sort( fNBins, &fBinMinEdges[0], &indices[0], !sortAsc );
526 std::vector<Double_t> binMinEdges(fNBins );
527 std::vector<Double_t> binMaxEdges(fNBins );
528 std::vector<UInt_t> binContent(fNBins );
529 fIndices.resize( fNBins );
530 for (UInt_t i = 0; i < fNBins; ++i) {
531 binMinEdges[i ] = fBinMinEdges[indices[i] ];
532 binMaxEdges[i ] = fBinMaxEdges[indices[i] ];
533 binContent[i] = fBinsContent[indices[i] ];
534 fIndices[indices[i] ] = i;
536 fBinMinEdges.swap(binMinEdges);
537 fBinMaxEdges.swap(binMaxEdges);
538 fBinsContent.swap(binContent);
544 fBinMinEdges.push_back(fBinMaxEdges.back());
545 fIsSortedAsc = kTRUE;
546 return &fBinMinEdges[0];
548 fBinMaxEdges.push_back(fBinMinEdges.back());
549 return &fBinMaxEdges[0];
554 const Double_t* TKDTreeBinning::GetBinCenter(UInt_t bin)
const {
556 Double_t* result =
new Double_t[fDim];
557 std::pair<const Double_t*, const Double_t*> binEdges = GetBinEdges(bin);
558 for (UInt_t i = 0; i < fDim; ++i) {
559 result[i] = (binEdges.second[i] + binEdges.first[i]) / 2.;
563 this->Warning(
"GetBinCenter",
"No such bin. Returning null pointer.");
564 this->Info(
"GetBinCenter",
"'bin' is between 0 and %d.", fNBins - 1);
569 const Double_t* TKDTreeBinning::GetBinWidth(UInt_t bin)
const {
571 Double_t* result =
new Double_t[fDim];
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]);
578 this->Warning(
"GetBinWidth",
"No such bin. Returning null pointer.");
579 this->Info(
"GetBinWidth",
"'bin' is between 0 and %d.", fNBins - 1);
584 UInt_t TKDTreeBinning::GetBinMaxDensity()
const {
590 UInt_t* indices =
new UInt_t[fNBins];
591 for (UInt_t i = 0; i < fNBins; ++i)
593 UInt_t result = *std::max_element(indices, indices + fNBins, CompareAsc(
this));
599 UInt_t TKDTreeBinning::GetBinMinDensity()
const {
605 UInt_t* indices =
new UInt_t[fNBins];
606 for (UInt_t i = 0; i < fNBins; ++i)
608 UInt_t result = *std::min_element(indices, indices + fNBins, CompareAsc(
this));
614 void TKDTreeBinning::FillBinData(ROOT::Fit::BinData & data)
const {
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) );
624 UInt_t TKDTreeBinning::FindBin(
const Double_t * point)
const {
626 Int_t inode = fDataBins->FindNode(point);
629 inode -= fDataBins->GetNNodes();
630 R__ASSERT( inode >= 0);
633 if (!fIsSorted)
return bin;
635 return fIndices[bin];
639 std::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.size() == 0) {
643 Error(
"GetPointsInBin",
"Internal data set is not valid");
647 Error(
"GetPointsInBin",
"Internal TKDTree is not valid");
651 Error(
"GetPointsInBin",
"Invalid bin number");
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] ];
663 thePoints[ipoint] = point;
670 void TKDTreeBinning::Streamer(TBuffer &b) {
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);
676 if (fDataBins)
delete fDataBins;
681 b.WriteClassBuffer(TKDTreeBinning::Class(),
this);