52 std::vector<Double_t> fWeights;
54 TKernel(Double_t weight, TKDE* kde);
55 void ComputeAdaptiveWeights();
56 Double_t operator()(Double_t x)
const;
57 Double_t GetWeight(Double_t x)
const;
58 Double_t GetFixedWeight()
const;
59 const std::vector<Double_t> & GetAdaptiveWeights()
const;
62 struct TKDE::KernelIntegrand {
63 enum EIntegralResult{kNorm, kMu, kSigma2, kUnitIntegration};
64 KernelIntegrand(
const TKDE* kde, EIntegralResult intRes);
65 Double_t operator()(Double_t x)
const;
68 EIntegralResult fIntegralResult;
73 fKernelFunction(nullptr),
78 fApproximateBias(nullptr),
80 fUseMirroring(false), fMirrorLeft(false), fMirrorRight(false), fAsymLeft(false), fAsymRight(false),
81 fUseBins(false), fNewData(false), fUseMinMaxFromData(false),
82 fNBins(0), fNEvents(0), fSumOfCounts(0), fUseBinsNEvents(0),
83 fMean(0.),fSigma(0.), fSigmaRob(0.), fXMin(0.), fXMax(0.),
84 fRho(0.), fAdaptiveBandwidthFactor(0.), fWeightSize(0)
90 if (fPDF)
delete fPDF;
91 if (fUpperPDF)
delete fUpperPDF;
92 if (fLowerPDF)
delete fLowerPDF;
93 if (fGraph)
delete fGraph;
94 if (fApproximateBias)
delete fApproximateBias;
95 if (fKernelFunction && fKernelType != kUserDefined)
delete fKernelFunction;
96 if (fKernel)
delete fKernel;
99 void TKDE::Instantiate(KernelFunction_Ptr kernfunc, UInt_t events,
const Double_t* data,
const Double_t* dataWeights, Double_t xMin, Double_t xMax,
const Option_t* option, Double_t rho) {
102 fData = std::vector<Double_t>(events, 0.0);
103 fEvents = std::vector<Double_t>(events, 0.0);
109 fApproximateBias = 0;
112 fUseMirroring =
false; fMirrorLeft =
false; fMirrorRight =
false;
113 fAsymLeft =
false; fAsymRight =
false;
114 fNBins = events < 10000 ? 100 : events / 10;
116 fUseBinsNEvents = 10000;
121 fUseMinMaxFromData = (fXMin >= fXMax);
123 fAdaptiveBandwidthFactor = 1.;
126 fCanonicalBandwidths = std::vector<Double_t>(kTotalKernels, 0.0);
127 fKernelSigmas2 = std::vector<Double_t>(kTotalKernels, -1.0);
128 fSettedOptions = std::vector<Bool_t>(4, kFALSE);
129 SetOptions(option, rho);
133 SetData(data, dataWeights);
134 SetKernelFunction(kernfunc);
138 void TKDE::SetOptions(
const Option_t* option, Double_t rho) {
140 TString opt = option;
142 std::string options = opt.Data();
144 std::vector<std::string> voption(numOpt,
"");
145 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
146 size_t pos = options.find_last_of(
';');
147 if (pos == std::string::npos) {
151 *it = options.substr(pos + 1);
152 options = options.substr(0, pos);
154 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end(); ++it) {
155 size_t pos = (*it).find(
':');
156 if (pos != std::string::npos) {
157 GetOptions((*it).substr(0, pos) , (*it).substr(pos + 1));
164 void TKDE::SetDrawOptions(
const Option_t* option, TString& plotOpt, TString& drawOpt) {
167 std::string options = TString(option).Data();
168 std::vector<std::string> voption(numOpt,
"");
169 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
170 size_t pos = options.find_last_of(
';');
171 if (pos == std::string::npos) {
175 *it = options.substr(pos + 1);
176 options = options.substr(0, pos);
178 Bool_t foundPlotOPt = kFALSE;
179 Bool_t foundDrawOPt = kFALSE;
180 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
181 size_t pos = (*it).find(
':');
182 if (pos == std::string::npos)
break;
183 TString optionType = (*it).substr(0, pos);
184 TString optionInstance = (*it).substr(pos + 1);
185 optionType.ToLower();
186 optionInstance.ToLower();
187 if (optionType.Contains(
"plot")) {
188 foundPlotOPt = kTRUE;
189 if (optionInstance.Contains(
"estimate") || optionInstance.Contains(
"errors") || optionInstance.Contains(
"confidenceinterval"))
190 plotOpt = optionInstance;
192 this->Warning(
"SetDrawOptions",
"Unknown plotting option: setting to KDE estimate plot.");
193 }
else if (optionType.Contains(
"drawoptions")) {
194 foundDrawOPt = kTRUE;
195 drawOpt = optionInstance;
199 this->Warning(
"SetDrawOptions",
"No plotting option: setting to KDE estimate plot.");
200 plotOpt =
"estimate";
203 this->Warning(
"SetDrawOptions",
"No drawing options: setting to default ones.");
208 void TKDE::GetOptions(std::string optionType, std::string option) {
210 if (optionType.compare(
"kerneltype") == 0) {
211 fSettedOptions[0] = kTRUE;
212 if (option.compare(
"gaussian") == 0) {
213 fKernelType = kGaussian;
214 }
else if (option.compare(
"epanechnikov") == 0) {
215 fKernelType = kEpanechnikov;
216 }
else if (option.compare(
"biweight") == 0) {
217 fKernelType = kBiweight;
218 }
else if (option.compare(
"cosinearch") == 0) {
219 fKernelType = kCosineArch;
220 }
else if (option.compare(
"userdefined") == 0) {
221 fKernelType = kUserDefined;
223 this->Warning(
"GetOptions",
"Unknown kernel type option: setting to Gaussian");
224 fKernelType = kGaussian;
226 }
else if (optionType.compare(
"iteration") == 0) {
227 fSettedOptions[1] = kTRUE;
228 if (option.compare(
"adaptive") == 0) {
229 fIteration = kAdaptive;
230 }
else if (option.compare(
"fixed") == 0) {
233 this->Warning(
"GetOptions",
"Unknown iteration option: setting to Adaptive");
234 fIteration = kAdaptive;
236 }
else if (optionType.compare(
"mirror") == 0) {
237 fSettedOptions[2] = kTRUE;
238 if (option.compare(
"nomirror") == 0) {
240 }
else if (option.compare(
"mirrorleft") == 0) {
241 fMirror = kMirrorLeft;
242 }
else if (option.compare(
"mirrorright") == 0) {
243 fMirror = kMirrorRight;
244 }
else if (option.compare(
"mirrorboth") == 0) {
245 fMirror = kMirrorBoth;
246 }
else if (option.compare(
"mirrorasymleft") == 0) {
247 fMirror = kMirrorAsymLeft;
248 }
else if (option.compare(
"mirrorasymleftright") == 0) {
249 fMirror = kMirrorAsymLeftRight;
250 }
else if (option.compare(
"mirrorasymright") == 0) {
251 fMirror = kMirrorAsymRight;
252 }
else if (option.compare(
"mirrorleftasymright") == 0) {
253 fMirror = kMirrorLeftAsymRight;
254 }
else if (option.compare(
"mirrorasymboth") == 0) {
255 fMirror = kMirrorAsymBoth;
257 this->Warning(
"GetOptions",
"Unknown mirror option: setting to NoMirror");
260 }
else if (optionType.compare(
"binning") == 0) {
261 fSettedOptions[3] = kTRUE;
262 if (option.compare(
"unbinned") == 0) {
263 fBinning = kUnbinned;
264 }
else if (option.compare(
"relaxedbinning") == 0) {
265 fBinning = kRelaxedBinning;
266 }
else if (option.compare(
"forcedbinning") == 0) {
267 fBinning = kForcedBinning;
269 this->Warning(
"GetOptions",
"Unknown binning option: setting to RelaxedBinning");
270 fBinning = kRelaxedBinning;
275 void TKDE::AssureOptions() {
277 if (!fSettedOptions[0]) {
278 fKernelType = kGaussian;
280 if (!fSettedOptions[1]) {
281 fIteration = kAdaptive;
283 if (!fSettedOptions[2]) {
286 if (!fSettedOptions[3]) {
287 fBinning = kRelaxedBinning;
291 void TKDE::CheckOptions(Bool_t isUserDefinedKernel) {
293 if (!(isUserDefinedKernel) && !(fKernelType >= kGaussian && fKernelType < kUserDefined)) {
294 Error(
"CheckOptions",
"Illegal user kernel type input! Use template constructor for user defined kernel.");
296 if (fIteration != kAdaptive && fIteration != kFixed) {
297 Warning(
"CheckOptions",
"Illegal user iteration type input - use default value !");
298 fIteration = kAdaptive;
300 if (!(fMirror >= kNoMirror && fMirror <= kMirrorAsymBoth)) {
301 Warning(
"CheckOptions",
"Illegal user mirroring type input - use default value !");
304 if (!(fBinning >= kUnbinned && fBinning <= kForcedBinning)) {
305 Warning(
"CheckOptions",
"Illegal user binning type input - use default value !");
306 fBinning = kRelaxedBinning;
309 Warning(
"CheckOptions",
"Tuning factor rho cannot be non-positive - use default value !");
314 void TKDE::SetKernelType(EKernelType kern) {
316 if (fKernelFunction && fKernelType != kUserDefined) {
317 delete fKernelFunction;
322 SetKernelFunction(0);
325 void TKDE::SetIteration(EIteration iter) {
333 void TKDE::SetMirror(EMirror mir) {
345 void TKDE::SetBinning(EBinning bin) {
352 void TKDE::SetNBins(UInt_t nbins) {
355 Error(
"SetNBins",
"Number of bins must be greater than zero.");
360 fWeightSize = fNBins / (fXMax - fXMin);
364 if (fBinning == kUnbinned)
365 Warning(
"SetNBins",
"Bin type using SetBinning must be set for using a binned evaluation");
367 Warning(
"SetNBins",
"Bin type using SetBinning or with SetUseBinsNEvents must be set for using a binned evaluation");
371 void TKDE::SetUseBinsNEvents(UInt_t nEvents) {
373 fUseBinsNEvents = nEvents;
377 void TKDE::SetTuneFactor(Double_t rho) {
387 void TKDE::SetRange(Double_t xMin, Double_t xMax) {
390 Error(
"SetRange",
"Minimum range cannot be bigger or equal than the maximum range! Present range values remain the same.");
395 fUseMinMaxFromData =
false;
401 void TKDE::SetUseBins() {
405 case kRelaxedBinning:
406 if (fNEvents >= fUseBinsNEvents) {
420 if (fUseBins && !fEvents.empty() ) {
421 SetBinCentreData(fXMin, fXMax);
427 void TKDE::SetMirror() {
429 fMirrorLeft = fMirror == kMirrorLeft || fMirror == kMirrorBoth || fMirror == kMirrorLeftAsymRight;
430 fMirrorRight = fMirror == kMirrorRight || fMirror == kMirrorBoth || fMirror == kMirrorAsymLeftRight;
431 fAsymLeft = fMirror == kMirrorAsymLeft || fMirror == kMirrorAsymLeftRight || fMirror == kMirrorAsymBoth;
432 fAsymRight = fMirror == kMirrorAsymRight || fMirror == kMirrorLeftAsymRight || fMirror == kMirrorAsymBoth;
433 fUseMirroring = fMirrorLeft || fMirrorRight ;
436 void TKDE::SetData(
const Double_t* data,
const Double_t* wgts) {
439 if (fNEvents) fData.reserve(fNEvents);
442 fEvents.assign(data, data + fNEvents);
443 if (wgts) fEventWeights.assign(wgts, wgts + fNEvents);
445 if (fUseMinMaxFromData) {
446 fXMin = *std::min_element(fEvents.begin(), fEvents.end());
447 fXMax = *std::max_element(fEvents.begin(), fEvents.end());
451 if (fNBins >= fNEvents) {
452 this->Warning(
"SetData",
"Default number of bins is greater or equal to number of events. Use SetNBins(UInt_t) to set the appropriate number of bins");
454 fWeightSize = fNBins / (fXMax - fXMin);
455 SetBinCentreData(fXMin, fXMax);
457 fWeightSize = fNEvents / (fXMax - fXMin);
470 void TKDE::ReInit() {
482 if (fKernelFunction) Error(
"ReInit",
"Kernel function pointer should be a nullptr when re-initializing after reading from a file");
484 if (fEvents.size() == 0) {
485 Error(
"ReInit",
"TKDE does not contain any data !");
489 SetKernelFunction(0);
494 void TKDE::InitFromNewData() {
498 Error(
"InitFromNewData",
"Re-felling is not supported with binning");
504 if (!fUseBins) fEvents = fData;
505 if (fUseMinMaxFromData) {
506 fXMin = *std::min_element(fEvents.begin(), fEvents.end());
507 fXMax = *std::max_element(fEvents.begin(), fEvents.end());
513 fWeightSize = fNEvents / (fXMax - fXMin);
520 void TKDE::SetMirroredEvents() {
522 std::vector<Double_t> originalEvents = fEvents;
523 std::vector<Double_t> originalWeights = fEventWeights;
525 fEvents.resize(2 * fNEvents, 0.0);
526 transform(fEvents.begin(), fEvents.begin() + fNEvents, fEvents.begin() + fNEvents,
527 std::bind(std::minus<Double_t>(), 2 * fXMin, std::placeholders::_1));
530 fEvents.resize((fMirrorLeft + 2) * fNEvents, 0.0);
531 transform(fEvents.begin(), fEvents.begin() + fNEvents, fEvents.begin() + (fMirrorLeft + 1) * fNEvents,
532 std::bind(std::minus<Double_t>(), 2 * fXMax, std::placeholders::_1));
534 if (!fEventWeights.empty() && (fMirrorLeft || fMirrorRight)) {
536 fEventWeights.insert(fEventWeights.end(), fEventWeights.begin(), fEventWeights.end() );
540 fNBins *= (fMirrorLeft + fMirrorRight + 1);
541 Double_t xmin = fMirrorLeft ? 2 * fXMin - fXMax : fXMin;
542 Double_t xmax = fMirrorRight ? 2 * fXMax - fXMin : fXMax;
543 SetBinCentreData(xmin, xmax);
549 fEvents = originalEvents;
550 fEventWeights = originalWeights;
553 void TKDE::SetMean() {
555 fMean = std::accumulate(fEvents.begin(), fEvents.end(), 0.0) / fEvents.size();
558 void TKDE::SetSigma(Double_t R) {
560 fSigma = std::sqrt(1. / (fEvents.size() - 1.) * (std::inner_product(fEvents.begin(), fEvents.end(), fEvents.begin(), 0.0) - fEvents.size() * std::pow(fMean, 2.)));
561 fSigmaRob = std::min(fSigma, R / 1.349);
564 void TKDE::SetKernel() {
566 UInt_t n = fData.size();
569 Double_t weight = fCanonicalBandwidths[kGaussian] * fSigmaRob * std::pow(3. / (8. * std::sqrt(M_PI)) * n, -0.2);
570 weight *= fRho * fCanonicalBandwidths[fKernelType] / fCanonicalBandwidths[kGaussian];
571 if (fKernel)
delete fKernel;
572 fKernel =
new TKernel(weight,
this);
573 if (fIteration == kAdaptive) {
574 fKernel->ComputeAdaptiveWeights();
579 void TKDE::SetKernelFunction(KernelFunction_Ptr kernfunc) {
581 assert(fKernelFunction == 0);
582 switch (fKernelType) {
584 fKernelFunction =
new ROOT::Math::WrappedMemFunction<TKDE, Double_t (TKDE::*)(Double_t) const>(*
this, &TKDE::GaussianKernel);
587 fKernelFunction =
new ROOT::Math::WrappedMemFunction<TKDE, Double_t (TKDE::*)(Double_t) const>(*
this, &TKDE::EpanechnikovKernel);
590 fKernelFunction =
new ROOT::Math::WrappedMemFunction<TKDE, Double_t (TKDE::*)(Double_t) const>(*
this, &TKDE::BiweightKernel);
593 fKernelFunction =
new ROOT::Math::WrappedMemFunction<TKDE, Double_t (TKDE::*)(Double_t) const>(*
this, &TKDE::CosineArchKernel);
596 fKernelFunction = kernfunc;
597 if (fKernelFunction) CheckKernelValidity();
602 fKernelFunction = kernfunc;
603 fKernelType = kUserDefined;
606 if (fKernelType == kUserDefined) {
607 if (fKernelFunction) {
608 CheckKernelValidity();
609 SetUserCanonicalBandwidth();
610 SetUserKernelSigma2();
613 Error(
"SetKernelFunction",
"User kernel function is not defined !");
617 assert(fKernelFunction);
619 SetCanonicalBandwidths();
623 void TKDE::SetCanonicalBandwidths() {
625 fCanonicalBandwidths[kGaussian] = 0.7764;
626 fCanonicalBandwidths[kEpanechnikov] = 1.7188;
627 fCanonicalBandwidths[kBiweight] = 2.03617;
628 fCanonicalBandwidths[kCosineArch] = 1.7663;
629 fCanonicalBandwidths[kUserDefined] = 1.0;
632 void TKDE::SetKernelSigmas2() {
634 fKernelSigmas2[kGaussian] = 1.0;
635 fKernelSigmas2[kEpanechnikov] = 1.0 / 5.0;
636 fKernelSigmas2[kBiweight] = 1.0 / 7.0;
637 fKernelSigmas2[kCosineArch] = 1.0 - 8.0 / std::pow(M_PI, 2);
640 TF1* TKDE::GetFunction(UInt_t npx, Double_t xMin, Double_t xMax) {
646 return GetKDEFunction(npx,xMin,xMax);
649 TF1* TKDE::GetUpperFunction(Double_t confidenceLevel, UInt_t npx, Double_t xMin, Double_t xMax) {
651 return GetPDFUpperConfidenceInterval(confidenceLevel,npx,xMin,xMax);
654 TF1* TKDE::GetLowerFunction(Double_t confidenceLevel, UInt_t npx, Double_t xMin, Double_t xMax) {
656 return GetPDFLowerConfidenceInterval(confidenceLevel,npx,xMin,xMax);
659 TF1* TKDE::GetApproximateBias(UInt_t npx, Double_t xMin, Double_t xMax) {
661 return GetKDEApproximateBias(npx,xMin,xMax);
664 void TKDE::Fill(Double_t data) {
667 this->Warning(
"Fill",
"Cannot fill data with data binned option. Data input ignored.");
670 fData.push_back(data);
675 void TKDE::Fill(Double_t data, Double_t weight) {
678 this->Warning(
"Fill",
"Cannot fill data with data binned option. Data input ignored.");
681 fData.push_back(data);
682 fEventWeights.push_back(weight);
687 Double_t TKDE::operator()(
const Double_t* x,
const Double_t*)
const {
692 Double_t TKDE::operator()(Double_t x)
const {
695 (
const_cast<TKDE*
>(
this))->ReInit();
697 if (!fKernel)
return TMath::QuietNaN();
699 return (*fKernel)(x);
702 Double_t TKDE::GetMean()
const {
704 if (fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
708 Double_t TKDE::GetSigma()
const {
710 if (fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
714 Double_t TKDE::GetRAMISE()
const {
716 Double_t result = 5. / 4. * fKernelSigmas2[fKernelType] * std::pow(fCanonicalBandwidths[fKernelType], 4) * std::pow(3. / (8. * std::sqrt(M_PI)) , -0.2) * fSigmaRob * std::pow(fNEvents, -0.8);
717 return std::sqrt(result);
720 TKDE::TKernel::TKernel(Double_t weight, TKDE* kde) :
723 fNWeights(kde->fData.size()),
724 fWeights(fNWeights, weight)
727 void TKDE::TKernel::ComputeAdaptiveWeights() {
729 std::vector<Double_t> weights = fWeights;
730 Double_t minWeight = weights[0] * 0.05;
731 unsigned int n = fKDE->fData.size();
732 assert( n == weights.size() );
733 bool useDataWeights = (fKDE->fBinCount.size() == n);
735 for (
unsigned int i = 0; i < n; ++i) {
737 if (useDataWeights && fKDE->fBinCount[i] <= 0)
continue;
738 f = (*fKDE->fKernel)(fKDE->fData[i]);
740 fKDE->Warning(
"ComputeAdativeWeights",
"function value is zero or negative for x = %f w = %f",
741 fKDE->fData[i],(useDataWeights) ? fKDE->fBinCount[i] : 1.);
742 weights[i] = std::max(weights[i] /= std::sqrt(f), minWeight);
743 fKDE->fAdaptiveBandwidthFactor += std::log(f);
746 Double_t kAPPROX_GEO_MEAN = 0.241970724519143365;
747 fKDE->fAdaptiveBandwidthFactor = fKDE->fUseMirroring ? kAPPROX_GEO_MEAN / fKDE->fSigmaRob : std::sqrt(std::exp(fKDE->fAdaptiveBandwidthFactor / fKDE->fData.size()));
748 transform(weights.begin(), weights.end(), fWeights.begin(),
749 std::bind(std::multiplies<Double_t>(), std::placeholders::_1, fKDE->fAdaptiveBandwidthFactor));
753 Double_t TKDE::TKernel::GetWeight(Double_t x)
const {
755 return fWeights[fKDE->Index(x)];
758 void TKDE::SetBinCentreData(Double_t xmin, Double_t xmax) {
760 fData.assign(fNBins, 0.0);
761 Double_t binWidth((xmax - xmin) / fNBins);
762 for (UInt_t i = 0; i < fNBins; ++i) {
763 fData[i] = xmin + (i + 0.5) * binWidth;
767 void TKDE::SetBinCountData() {
771 fBinCount.resize(fNBins);
774 if (!fEventWeights.empty() ) {
775 for (UInt_t i = 0; i < fNEvents; ++i) {
776 if (fEvents[i] >= fXMin && fEvents[i] < fXMax) {
777 fBinCount[Index(fEvents[i])] += fEventWeights[i];
778 fSumOfCounts += fEventWeights[i];
785 for (UInt_t i = 0; i < fNEvents; ++i) {
786 if (fEvents[i] >= fXMin && fEvents[i] < fXMax) {
787 fBinCount[Index(fEvents[i])] += 1;
793 else if (!fEventWeights.empty() ) {
794 fBinCount = fEventWeights;
796 for (UInt_t i = 0; i < fNEvents; ++i)
797 fSumOfCounts += fEventWeights[i];
800 fSumOfCounts = fNEvents;
805 void TKDE::Draw(
const Option_t* opt) {
824 TString plotOpt = opt;
826 TString drawOpt = plotOpt;
827 if(gPad && !plotOpt.Contains(
"same")) {
830 if (plotOpt.Contains(
"errors")) {
831 drawOpt.ReplaceAll(
"errors",
"");
834 else if (plotOpt.Contains(
"confidenceinterval") ||
835 plotOpt.Contains(
"confinterval")) {
837 drawOpt.ReplaceAll(
"confidenceinterval",
"");
838 drawOpt.ReplaceAll(
"confinterval",
"");
839 Double_t level = 0.95;
840 const char * s = strstr(plotOpt.Data(),
"interval@");
842 if (s != 0) sscanf(s,
"interval@%lf",&level);
843 if((level <= 0) || (level >= 1)) {
844 Warning(
"Draw",
"given confidence level %.3lf is invalid - use default 0.95",level);
847 DrawConfidenceInterval(drawOpt,level);
850 if (fPDF)
delete fPDF;
851 fPDF = GetKDEFunction();
856 void TKDE::DrawErrors(TString& drawOpt) {
858 if (fGraph)
delete fGraph;
859 fGraph = GetGraphWithErrors();
860 fGraph->Draw(drawOpt.Data());
863 TGraphErrors* TKDE::GetGraphWithErrors(UInt_t npx,
double xmin,
double xmax) {
864 if (xmin>= xmax) { xmin = fXMin; xmax = fXMax; }
867 Double_t* x =
new Double_t[n + 1];
868 Double_t* ex =
new Double_t[n + 1];
869 Double_t* y =
new Double_t[n + 1];
870 Double_t* ey =
new Double_t[n + 1];
871 for (UInt_t i = 0; i <= n; ++i) {
872 x[i] = xmin + i * (xmax - xmin) / n;
873 y[i] = (*this)(x[i]);
875 ey[i] = this->GetError(x[i]);
877 TGraphErrors* ge =
new TGraphErrors(n, &x[0], &y[0], &ex[0], &ey[0]);
878 ge->SetName(
"kde_graph_error");
879 ge->SetTitle(
"Errors");
887 void TKDE::DrawConfidenceInterval(TString& drawOpt,
double cl) {
889 GetKDEFunction()->Draw(drawOpt.Data());
890 TF1* upper = GetPDFUpperConfidenceInterval(cl);
891 upper->SetLineColor(kBlue);
892 upper->Draw((
"same" + drawOpt).Data());
893 TF1* lower = GetPDFLowerConfidenceInterval(cl);
894 lower->SetLineColor(kRed);
895 lower->Draw((
"same" + drawOpt).Data());
896 if (fUpperPDF)
delete fUpperPDF;
897 if (fLowerPDF)
delete fLowerPDF;
902 Double_t TKDE::GetFixedWeight()
const {
904 Double_t result = -1.;
905 if (fIteration == TKDE::kAdaptive) {
906 this->Warning(
"GetFixedWeight()",
"Fixed iteration option not enabled. Returning %f.", result);
908 result = fKernel->GetFixedWeight();
913 const Double_t * TKDE::GetAdaptiveWeights()
const {
915 if (fIteration != TKDE::kAdaptive) {
916 this->Warning(
"GetFixedWeight()",
"Adaptive iteration option not enabled. Returning a NULL pointer<");
919 if (fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
920 return &(fKernel->GetAdaptiveWeights()).front();
923 Double_t TKDE::TKernel::GetFixedWeight()
const {
928 const std::vector<Double_t> & TKDE::TKernel::GetAdaptiveWeights()
const {
933 Double_t TKDE::TKernel::operator()(Double_t x)
const {
935 Double_t result(0.0);
936 UInt_t n = fKDE->fData.size();
938 Bool_t useBins = (fKDE->fBinCount.size() == n);
939 Double_t nSum = (useBins) ? fKDE->fSumOfCounts : fKDE->fNEvents;
942 for (UInt_t i = 0; i < n; ++i) {
943 Double_t binCount = (useBins) ? fKDE->fBinCount[i] : 1.0;
944 result += binCount / fWeights[i] * (*fKDE->fKernelFunction)((x - fKDE->fData[i]) / fWeights[i]);
945 if (fKDE->fAsymLeft) {
946 result -= binCount / fWeights[i] * (*fKDE->fKernelFunction)((x - (2. * fKDE->fXMin - fKDE->fData[i])) / fWeights[i]);
948 if (fKDE->fAsymRight) {
949 result -= binCount / fWeights[i] * (*fKDE->fKernelFunction)((x - (2. * fKDE->fXMax - fKDE->fData[i])) / fWeights[i]);
966 if ( TMath::IsNaN(result) ) {
967 fKDE->Warning(
"operator()",
"Result is NaN for x %f \n",x);
970 return result / nSum;
973 UInt_t TKDE::Index(Double_t x)
const {
975 Int_t bin = Int_t((x - fXMin) * fWeightSize);
976 if (bin == (Int_t)fData.size())
return --bin;
977 if (fUseMirroring && (fMirrorLeft || !fMirrorRight)) {
978 bin += fData.size() / (fMirrorLeft + fMirrorRight + 1);
980 if (bin > (Int_t)fData.size()) {
981 return (Int_t)(fData.size()) - 1;
982 }
else if (bin <= 0) {
988 Double_t TKDE::UpperConfidenceInterval(
const Double_t* x,
const Double_t* p)
const {
990 Double_t f = (*this)(x);
991 Double_t sigma = GetError(*x);
992 Double_t prob = 1. - (1.-*p)/2;
993 Double_t z = ROOT::Math::normal_quantile(prob, 1.0);
994 return f + z * sigma;
997 Double_t TKDE::LowerConfidenceInterval(
const Double_t* x,
const Double_t* p)
const {
999 Double_t f = (*this)(x);
1000 Double_t sigma = GetError(*x);
1001 Double_t prob = (1.-*p)/2;
1002 Double_t z = ROOT::Math::normal_quantile(prob, 1.0);
1003 return f + z * sigma;
1007 Double_t TKDE::GetBias(Double_t x)
const {
1009 ROOT::Math::WrappedFunction<const TKDE&> kern(*
this);
1010 ROOT::Math::RichardsonDerivator rd;
1011 rd.SetFunction(kern);
1012 Double_t df2 = rd.Derivative2(x);
1013 Double_t weight = fKernel->GetWeight(x);
1014 return 0.5 * fKernelSigmas2[fKernelType] * std::pow(weight, 2) * df2;
1016 Double_t TKDE::GetError(Double_t x)
const {
1018 Double_t kernelL2Norm = ComputeKernelL2Norm();
1019 Double_t f = (*this)(x);
1020 Double_t weight = fKernel->GetWeight(x);
1021 Double_t result = f * kernelL2Norm / (fNEvents * weight);
1022 return std::sqrt(result);
1025 void TKDE::CheckKernelValidity() {
1027 Double_t valid = kTRUE;
1028 Double_t unity = ComputeKernelIntegral();
1029 valid = valid && unity == 1.;
1031 Error(
"CheckKernelValidity",
"Kernel's integral is %f",unity);
1033 Double_t mu = ComputeKernelMu();
1034 valid = valid && mu == 0.;
1036 Error(
"CheckKernelValidity",
"Kernel's mu is %f" ,mu);
1038 Double_t sigma2 = ComputeKernelSigma2();
1039 valid = valid && sigma2 > 0 && sigma2 != std::numeric_limits<Double_t>::infinity();
1041 Error(
"CheckKernelValidity",
"Kernel's sigma2 is %f",sigma2);
1044 Error(
"CheckKernelValidity",
"Validation conditions: the kernel's integral must be 1, the kernel's mu must be zero and the kernel's sigma2 must be finite positive to be a suitable kernel.");
1049 Double_t TKDE::ComputeKernelL2Norm()
const {
1051 ROOT::Math::IntegratorOneDim ig(ROOT::Math::IntegrationOneDim::kGAUSS);
1052 KernelIntegrand kernel(
this, TKDE::KernelIntegrand::kNorm);
1053 ig.SetFunction(kernel);
1054 Double_t result = ig.Integral();
1058 Double_t TKDE::ComputeKernelSigma2()
const {
1060 ROOT::Math::IntegratorOneDim ig( ROOT::Math::IntegrationOneDim::kGAUSS);
1061 KernelIntegrand kernel(
this, TKDE::KernelIntegrand::kSigma2);
1062 ig.SetFunction(kernel);
1063 Double_t result = ig.Integral();
1067 Double_t TKDE::ComputeKernelMu()
const {
1069 ROOT::Math::IntegratorOneDim ig(ROOT::Math::IntegrationOneDim::kGAUSS);
1070 KernelIntegrand kernel(
this, TKDE::KernelIntegrand::kMu);
1071 ig.SetFunction(kernel);
1072 Double_t result = ig.Integral();
1076 Double_t TKDE::ComputeKernelIntegral()
const {
1078 ROOT::Math::IntegratorOneDim ig(ROOT::Math::IntegrationOneDim::kGAUSS);
1079 KernelIntegrand kernel(
this, TKDE::KernelIntegrand::kUnitIntegration);
1080 ig.SetFunction(kernel);
1081 Double_t result = ig.Integral();
1085 void TKDE::ComputeDataStats() {
1087 if (!fEventWeights.empty() ) {
1089 double x1 = fXMin - 0.001*(fXMax-fXMin);
1090 double x2 = fXMax + 0.001*(fXMax-fXMin);
1091 TH1D h1(
"temphist",
"", 500, x1, x2);
1092 h1.FillN(fEvents.size(), fEvents.data(), fEventWeights.data() );
1093 assert (h1.GetSumOfWeights() > 0) ;
1094 fMean = h1.GetMean();
1095 fSigma = h1.GetRMS();
1097 Double_t quantiles[2] = {0.0, 0.0};
1098 Double_t prob[2] = {0.25, 0.75};
1099 h1.GetQuantiles(2, quantiles, prob);
1100 Double_t midspread = quantiles[1] - quantiles[0];
1101 fSigmaRob = std::min(fSigma, midspread / 1.349);
1108 Double_t midspread = ComputeMidspread();
1109 SetSigma(midspread);
1114 Double_t TKDE::ComputeMidspread () {
1116 std::sort(fEvents.begin(), fEvents.end());
1117 Double_t quantiles[2] = {0.0, 0.0};
1118 Double_t prob[2] = {0.25, 0.75};
1119 TMath::Quantiles(fEvents.size(), 2, &fEvents[0], quantiles, prob);
1120 Double_t lowerquartile = quantiles[0];
1121 Double_t upperquartile = quantiles[1];
1122 return upperquartile - lowerquartile;
1125 void TKDE::SetUserCanonicalBandwidth() {
1127 fCanonicalBandwidths[kUserDefined] = std::pow(ComputeKernelL2Norm() / std::pow(ComputeKernelSigma2(), 2), 1. / 5.);
1130 void TKDE::SetUserKernelSigma2() {
1132 fKernelSigmas2[kUserDefined] = ComputeKernelSigma2();
1135 TKDE::KernelIntegrand::KernelIntegrand(
const TKDE* kde, EIntegralResult intRes) : fKDE(kde), fIntegralResult(intRes) {
1139 Double_t TKDE::KernelIntegrand::operator()(Double_t x)
const {
1141 if (fIntegralResult == kNorm) {
1142 return std::pow((*fKDE->fKernelFunction)(x), 2);
1143 }
else if (fIntegralResult == kMu) {
1144 return x * (*fKDE->fKernelFunction)(x);
1145 }
else if (fIntegralResult == kSigma2) {
1146 return std::pow(x, 2) * (*fKDE->fKernelFunction)(x);
1147 }
else if (fIntegralResult == kUnitIntegration) {
1148 return (*fKDE->fKernelFunction)(x);
1154 TF1* TKDE::GetKDEFunction(UInt_t npx, Double_t xMin , Double_t xMax) {
1156 TString name =
"KDEFunc_"; name+= GetName();
1157 TString title =
"KDE "; title+= GetTitle();
1158 if (xMin >= xMax) { xMin = fXMin; xMax = fXMax; }
1160 bool previous = TF1::DefaultAddToGlobalList(kFALSE);
1161 TF1 * pdf =
new TF1(name.Data(),
this, xMin, xMax, 0);
1162 TF1::DefaultAddToGlobalList(previous);
1163 if (npx > 0) pdf->SetNpx(npx);
1164 pdf->SetTitle(title);
1168 TF1* TKDE::GetPDFUpperConfidenceInterval(Double_t confidenceLevel, UInt_t npx, Double_t xMin , Double_t xMax) {
1171 name.Form(
"KDE_UpperCL%f5.3_%s",confidenceLevel,GetName());
1172 if (xMin >= xMax) { xMin = fXMin; xMax = fXMax; }
1173 TF1 * upperPDF =
new TF1(name,
this, &TKDE::UpperConfidenceInterval, xMin, xMax, 1);
1174 upperPDF->SetParameter(0, confidenceLevel);
1175 if (npx > 0) upperPDF->SetNpx(npx);
1176 TF1 * f = (TF1*)upperPDF->Clone();
1181 TF1* TKDE::GetPDFLowerConfidenceInterval(Double_t confidenceLevel, UInt_t npx, Double_t xMin , Double_t xMax) {
1184 name.Form(
"KDE_LowerCL%f5.3_%s",confidenceLevel,GetName());
1185 if (xMin >= xMax) { xMin = fXMin; xMax = fXMax; }
1186 TF1 * lowerPDF =
new TF1(name,
this, &TKDE::LowerConfidenceInterval, xMin, xMax, 1);
1187 lowerPDF->SetParameter(0, confidenceLevel);
1188 if (npx > 0) lowerPDF->SetNpx(npx);
1189 TF1 * f = (TF1*)lowerPDF->Clone();
1194 TF1* TKDE::GetKDEApproximateBias(UInt_t npx, Double_t xMin , Double_t xMax) {
1196 TString name =
"KDE_Bias_"; name += GetName();
1197 if (xMin >= xMax) { xMin = fXMin; xMax = fXMax; }
1198 TF1 * approximateBias =
new TF1(name,
this, &TKDE::ApproximateBias, xMin, xMax, 0);
1199 if (npx > 0) approximateBias->SetNpx(npx);
1200 TF1 * f = (TF1*)approximateBias->Clone();
1201 delete approximateBias;