52 std::vector<Double_t> fWeights;
55 void ComputeAdaptiveWeights();
63 enum EIntegralResult{
kNorm, kMu, kSigma2, kUnitIntegration};
68 EIntegralResult fIntegralResult;
118 fData = std::vector<Double_t>(events, 0.0);
119 fEvents = std::vector<Double_t>(events, 0.0);
130 fNBins = events < 10000 ? 100 : events / 10;
157 std::string options = opt.
Data();
159 std::vector<std::string> voption(numOpt,
"");
160 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
161 size_t pos = options.find_last_of(
';');
162 if (pos == std::string::npos) {
166 *it = options.substr(pos + 1);
167 options = options.substr(0, pos);
169 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end(); ++it) {
170 size_t pos = (*it).find(
':');
171 if (pos != std::string::npos) {
172 GetOptions((*it).substr(0, pos) , (*it).substr(pos + 1));
183 std::vector<std::string> voption(numOpt,
"");
184 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
185 size_t pos = options.find_last_of(
';');
186 if (pos == std::string::npos) {
190 *it = options.substr(pos + 1);
191 options = options.substr(0, pos);
195 for (std::vector<std::string>::iterator it = voption.begin(); it != voption.end() && !options.empty(); ++it) {
196 size_t pos = (*it).find(
':');
197 if (pos == std::string::npos)
break;
198 TString optionType = (*it).substr(0, pos);
199 TString optionInstance = (*it).substr(pos + 1);
203 foundPlotOPt =
kTRUE;
204 if (optionInstance.
Contains(
"estimate") || optionInstance.
Contains(
"errors") || optionInstance.
Contains(
"confidenceinterval"))
205 plotOpt = optionInstance;
207 this->
Warning(
"SetDrawOptions",
"Unknown plotting option: setting to KDE estimate plot.");
208 }
else if (optionType.
Contains(
"drawoptions")) {
209 foundDrawOPt =
kTRUE;
210 drawOpt = optionInstance;
214 this->
Warning(
"SetDrawOptions",
"No plotting option: setting to KDE estimate plot.");
215 plotOpt =
"estimate";
218 this->
Warning(
"SetDrawOptions",
"No drawing options: setting to default ones.");
225 if (optionType.compare(
"kerneltype") == 0) {
227 if (option.compare(
"gaussian") == 0) {
229 }
else if (option.compare(
"epanechnikov") == 0) {
231 }
else if (option.compare(
"biweight") == 0) {
233 }
else if (option.compare(
"cosinearch") == 0) {
235 }
else if (option.compare(
"userdefined") == 0) {
238 this->
Warning(
"GetOptions",
"Unknown kernel type option: setting to Gaussian");
241 }
else if (optionType.compare(
"iteration") == 0) {
243 if (option.compare(
"adaptive") == 0) {
245 }
else if (option.compare(
"fixed") == 0) {
248 this->
Warning(
"GetOptions",
"Unknown iteration option: setting to Adaptive");
251 }
else if (optionType.compare(
"mirror") == 0) {
253 if (option.compare(
"nomirror") == 0) {
255 }
else if (option.compare(
"mirrorleft") == 0) {
257 }
else if (option.compare(
"mirrorright") == 0) {
259 }
else if (option.compare(
"mirrorboth") == 0) {
261 }
else if (option.compare(
"mirrorasymleft") == 0) {
263 }
else if (option.compare(
"mirrorasymleftright") == 0) {
265 }
else if (option.compare(
"mirrorasymright") == 0) {
267 }
else if (option.compare(
"mirrorleftasymright") == 0) {
269 }
else if (option.compare(
"mirrorasymboth") == 0) {
272 this->
Warning(
"GetOptions",
"Unknown mirror option: setting to NoMirror");
275 }
else if (optionType.compare(
"binning") == 0) {
277 if (option.compare(
"unbinned") == 0) {
279 }
else if (option.compare(
"relaxedbinning") == 0) {
281 }
else if (option.compare(
"forcedbinning") == 0) {
284 this->
Warning(
"GetOptions",
"Unknown binning option: setting to RelaxedBinning");
309 Error(
"CheckOptions",
"Illegal user kernel type input! Use template constructor for user defined kernel.");
312 Warning(
"CheckOptions",
"Illegal user iteration type input - use default value !");
316 Warning(
"CheckOptions",
"Illegal user mirroring type input - use default value !");
320 Warning(
"CheckOptions",
"Illegal user binning type input - use default value !");
324 Warning(
"CheckOptions",
"Tuning factor rho cannot be non-positive - use default value !");
371 Error(
"SetNBins",
"Number of bins must be greater than zero.");
380 Warning(
"SetNBins",
"Bin type using SetBinning must set for using a binned evaluation");
407 Error(
"SetRange",
"Minimum range cannot be bigger or equal than the maximum range! Present range values remain the same.");
462 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");
502 std::vector<Double_t> originalEvents =
fEvents;
507 std::bind(std::minus<Double_t>(), 2 *
fXMin, std::placeholders::_1));
512 std::bind(std::minus<Double_t>(), 2 *
fXMax, std::placeholders::_1));
554 fKernel->ComputeAdaptiveWeights();
592 Error(
"SetKernelFunction",
"User kernel function is not defined !");
646 this->
Warning(
"Fill",
"Cannot fill data with data binned option. Data input ignored.");
649 fData.push_back(data);
657 this->
Warning(
"Fill",
"Cannot fill data with data binned option. Data input ignored.");
660 fData.push_back(data);
673 if (
fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
679 if (
fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
685 if (
fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
698fNWeights(kde->fData.size()),
699fWeights(fNWeights, weight)
702void TKDE::TKernel::ComputeAdaptiveWeights() {
704 std::vector<Double_t> weights = fWeights;
705 Double_t minWeight = weights[0] * 0.05;
706 unsigned int n = fKDE->fData.size();
707 assert(
n == weights.size() );
708 bool useDataWeights = (fKDE->fBinCount.size() ==
n);
710 for (
unsigned int i = 0; i <
n; ++i) {
712 if (useDataWeights && fKDE->fBinCount[i] <= 0)
continue;
713 f = (*fKDE->fKernel)(fKDE->fData[i]);
715 fKDE->Warning(
"ComputeAdativeWeights",
"function value is zero or negative for x = %f w = %f",
716 fKDE->fData[i],(useDataWeights) ? fKDE->fBinCount[i] : 1.);
717 weights[i] = std::max(weights[i] /=
std::sqrt(
f), minWeight);
718 fKDE->fAdaptiveBandwidthFactor +=
std::log(
f);
721 Double_t kAPPROX_GEO_MEAN = 0.241970724519143365;
722 fKDE->fAdaptiveBandwidthFactor = fKDE->fUseMirroring ? kAPPROX_GEO_MEAN / fKDE->fSigmaRob :
std::sqrt(
std::exp(fKDE->fAdaptiveBandwidthFactor / fKDE->fData.size()));
723 transform(weights.begin(), weights.end(), fWeights.begin(),
724 std::bind(std::multiplies<Double_t>(), std::placeholders::_1, fKDE->fAdaptiveBandwidthFactor));
730 return fWeights[fKDE->Index(
x)];
809 else if (plotOpt.
Contains(
"confidenceinterval") ||
815 const char *
s = strstr(plotOpt.
Data(),
"interval@");
817 if (
s != 0) sscanf(
s,
"interval@%lf",&level);
818 if((level <= 0) || (level >= 1)) {
819 Warning(
"Draw",
"given confidence level %.3lf is invalid - use default 0.95",level);
846 for (
UInt_t i = 0; i <=
n; ++i) {
848 y[i] = (*this)(
x[i]);
853 ge->
SetName(
"kde_graph_error");
867 upper->
Draw((
"same" + drawOpt).Data());
870 lower->
Draw((
"same" + drawOpt).Data());
881 this->
Warning(
"GetFixedWeight()",
"Fixed iteration option not enabled. Returning %f.", result);
883 result =
fKernel->GetFixedWeight();
891 this->
Warning(
"GetFixedWeight()",
"Adaptive iteration option not enabled. Returning a NULL pointer<");
894 if (
fNewData) (
const_cast<TKDE*
>(
this))->InitFromNewData();
895 return &(
fKernel->GetAdaptiveWeights()).front();
898Double_t TKDE::TKernel::GetFixedWeight()
const {
903const std::vector<Double_t> & TKDE::TKernel::GetAdaptiveWeights()
const {
913 Bool_t useBins = (fKDE->fBinCount.size() ==
n);
914 Double_t nSum = (useBins) ? fKDE->fSumOfCounts : fKDE->fNEvents;
918 Double_t binCount = (useBins) ? fKDE->fBinCount[i] : 1.0;
920 result += binCount / fWeights[i] * (*fKDE->fKernelFunction)((
x - fKDE->fData[i]) / fWeights[i]);
921 if (fKDE->fAsymLeft) {
922 result -= binCount / fWeights[i] * (*fKDE->fKernelFunction)((
x - (2. * fKDE->fXMin - fKDE->fData[i])) / fWeights[i]);
924 if (fKDE->fAsymRight) {
925 result -= binCount / fWeights[i] * (*fKDE->fKernelFunction)((
x - (2. * fKDE->fXMax - fKDE->fData[i])) / fWeights[i]);
941 fKDE->Warning(
"operator()",
"Result is NaN for x %f \n",
x);
944 return result / nSum;
956 }
else if (bin <= 0) {
1003 valid = valid && unity == 1.;
1005 Error(
"CheckKernelValidity",
"Kernel's integral is %f",unity);
1008 valid = valid && mu == 0.;
1010 Error(
"CheckKernelValidity",
"Kernel's mu is %f" ,mu);
1013 valid = valid && sigma2 > 0 && sigma2 != std::numeric_limits<Double_t>::infinity();
1015 Error(
"CheckKernelValidity",
"Kernel's sigma2 is %f",sigma2);
1018 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.");
1053 KernelIntegrand kernel(
this, TKDE::KernelIntegrand::kUnitIntegration);
1071 Double_t quantiles[2] = {0.0, 0.0};
1074 Double_t midspread = quantiles[1] - quantiles[0];
1091 Double_t quantiles[2] = {0.0, 0.0};
1094 Double_t lowerquartile = quantiles[0];
1095 Double_t upperquartile = quantiles[1];
1096 return upperquartile - lowerquartile;
1109TKDE::KernelIntegrand::KernelIntegrand(
const TKDE* kde, EIntegralResult intRes) : fKDE(kde), fIntegralResult(intRes) {
1115 if (fIntegralResult ==
kNorm) {
1116 return std::pow((*fKDE->fKernelFunction)(
x), 2);
1117 }
else if (fIntegralResult == kMu) {
1118 return x * (*fKDE->fKernelFunction)(
x);
1119 }
else if (fIntegralResult == kSigma2) {
1120 return std::pow(
x, 2) * (*fKDE->fKernelFunction)(
x);
1121 }
else if (fIntegralResult == kUnitIntegration) {
1122 return (*fKDE->fKernelFunction)(
x);
1132 if (xMin >= xMax) { xMin =
fXMin; xMax =
fXMax; }
1135 TF1 * pdf =
new TF1(
name.Data(),
this, xMin, xMax, 0);
1137 if (npx > 0) pdf->
SetNpx(npx);
1145 name.Form(
"KDE_UpperCL%f5.3_%s",confidenceLevel,
GetName());
1146 if (xMin >= xMax) { xMin =
fXMin; xMax =
fXMax; }
1149 if (npx > 0) upperPDF->
SetNpx(npx);
1158 name.Form(
"KDE_LowerCL%f5.3_%s",confidenceLevel,
GetName());
1159 if (xMin >= xMax) { xMin =
fXMin; xMax =
fXMax; }
1162 if (npx > 0) lowerPDF->
SetNpx(npx);
1171 if (xMin >= xMax) { xMin =
fXMin; xMax =
fXMax; }
1173 if (npx > 0) approximateBias->
SetNpx(npx);
1175 delete approximateBias;
#define R(a, b, c, d, e, f, g, h, i)
static const double x2[5]
static const double x1[5]
double pow(double, double)
TRObject operator()(const T1 &t1) const
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
User Class for performing numerical integration of a function in one dimension.
void SetFunction(Function &f)
method to set the a generic integration function
double Integral(Function &f, double a, double b)
evaluate the Integral of a function f over the defined interval (a,b)
User class for calculating the derivatives of a function.
double Derivative2(double x)
Returns the second derivative of the function at point x, computed by Richardson's extrapolation meth...
void SetFunction(const IGenFunction &f)
Set function for derivative calculation (copy the function if option has been enabled in the construc...
Template class to wrap any C++ callable object which takes one argument i.e.
Template class to wrap any member function of a class taking a double and returning a double in a 1D ...
virtual void SetLineColor(Color_t lcolor)
Set the line color.
virtual void SetTitle(const char *title="")
Set function title if title has the form "fffffff;xxxx;yyyy", it is assumed that the function title i...
virtual void SetNpx(Int_t npx=100)
Set the number of points used to draw the function.
virtual void Draw(Option_t *option="")
Draw this function with its current attributes.
static Bool_t DefaultAddToGlobalList(Bool_t on=kTRUE)
Static method to add/avoid to add automatically functions to the global list (gROOT->GetListOfFunctio...
virtual void SetParameter(Int_t param, Double_t value)
A TGraphErrors is a TGraph with error bars.
virtual void SetName(const char *name="")
Set graph name.
virtual void SetTitle(const char *title="")
Set graph title.
virtual void Draw(Option_t *chopt="")
Draw this graph with its current attributes.
1-D histogram with a double per channel (see TH1 documentation)}
virtual Int_t GetQuantiles(Int_t nprobSum, Double_t *q, const Double_t *probSum=0)
Compute Quantiles for this histogram Quantile x_q of a probability distribution Function F is defined...
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Double_t GetRMS(Int_t axis=1) const
virtual void FillN(Int_t ntimes, const Double_t *x, const Double_t *w, Int_t stride=1)
Fill this histogram with an array x and weights w.
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Kernel Density Estimation class.
TF1 * GetPDFUpperConfidenceInterval(Double_t confidenceLevel=0.95, UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
TF1 * GetKDEApproximateBias(UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
void SetData(const Double_t *data, const Double_t *weights)
std::vector< Double_t > fKernelSigmas2
Double_t ComputeKernelL2Norm() const
TF1 * GetPDFLowerConfidenceInterval(Double_t confidenceLevel=0.95, UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
void SetKernelType(EKernelType kern)
std::vector< Double_t > fCanonicalBandwidths
void SetKernelFunction(KernelFunction_Ptr kernfunc=0)
Double_t UpperConfidenceInterval(const Double_t *x, const Double_t *p) const
Double_t ApproximateBias(const Double_t *x, const Double_t *) const
Double_t ComputeMidspread()
void DrawConfidenceInterval(TString &drawOpt, double cl=0.95)
void SetUserCanonicalBandwidth()
void CheckKernelValidity()
const Double_t * GetAdaptiveWeights() const
Double_t fAdaptiveBandwidthFactor
Double_t LowerConfidenceInterval(const Double_t *x, const Double_t *p) const
std::vector< Double_t > fBinCount
Double_t GetRAMISE() const
void SetIteration(EIteration iter)
Double_t ComputeKernelIntegral() const
Double_t CosineArchKernel(Double_t x) const
Double_t operator()(Double_t x) const
void SetUserKernelSigma2()
Double_t GetBias(Double_t x) const
std::vector< Double_t > fData
TGraphErrors * GetGraphWithErrors(UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
void SetUseBinsNEvents(UInt_t nEvents)
std::vector< Double_t > fEvents
Double_t GetError(Double_t x) const
TF1 * GetKDEFunction(UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
void SetBinning(EBinning)
void GetOptions(std::string optionType, std::string option)
std::vector< Bool_t > fSettedOptions
Double_t GaussianKernel(Double_t x) const
void SetRange(Double_t xMin, Double_t xMax)
virtual void Draw(const Option_t *option="")
Double_t ComputeKernelSigma2() const
void SetOptions(const Option_t *option, Double_t rho)
Double_t GetFixedWeight() const
TF1 * GetFunction(UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
TF1 * GetUpperFunction(Double_t confidenceLevel=0.95, UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
void Instantiate(KernelFunction_Ptr kernfunc, UInt_t events, const Double_t *data, const Double_t *weight, Double_t xMin, Double_t xMax, const Option_t *option, Double_t rho)
void SetDrawOptions(const Option_t *option, TString &plotOpt, TString &drawOpt)
void SetCanonicalBandwidths()
void SetBinCentreData(Double_t xmin, Double_t xmax)
void SetTuneFactor(Double_t rho)
UInt_t Index(Double_t x) const
Double_t ComputeKernelMu() const
void DrawErrors(TString &drawOpt)
void SetNBins(UInt_t nbins)
void CheckOptions(Bool_t isUserDefinedKernel=kFALSE)
Double_t EpanechnikovKernel(Double_t x) const
Double_t BiweightKernel(Double_t x) const
Bool_t fUseMinMaxFromData
Double_t GetSigma() const
void SetSigma(Double_t R)
std::vector< Double_t > fEventWeights
TF1 * GetApproximateBias(UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
TF1 * GetLowerFunction(Double_t confidenceLevel=0.95, UInt_t npx=100, Double_t xMin=1.0, Double_t xMax=0.0)
KernelFunction_Ptr fKernelFunction
friend struct KernelIntegrand
virtual const char * GetTitle() const
Returns title of object.
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
virtual const char * GetName() const
Returns name of object.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
void ToLower()
Change string to lower-case.
const char * Data() const
TString & ReplaceAll(const TString &s1, const TString &s2)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
double normal_quantile(double z, double sigma)
Inverse ( ) of the cumulative distribution function of the lower tail of the normal (Gaussian) distri...
double inner_product(const LAVector &, const LAVector &)
static constexpr double s
void Quantiles(Int_t n, Int_t nprob, Double_t *x, Double_t *quantiles, Double_t *prob, Bool_t isSorted=kTRUE, Int_t *index=0, Int_t type=7)
Computes sample quantiles, corresponding to the given probabilities.