Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RF] New PDF: gaussian with double sided exponential tails #17976

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion roofit/roofit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooFit
RooFunctor1DBinding.h
RooFunctorBinding.h
RooGamma.h
RooGaussExpTails.h
RooGaussian.h
RooGaussModel.h
RooGExpModel.h
@@ -104,10 +105,11 @@ ROOT_STANDARD_LIBRARY_PACKAGE(RooFit
src/RooDstD0BG.cxx
src/RooExponential.cxx
src/RooLegacyExpPoly.cxx
src/RooPowerSum.cxx
src/RooPowerSum.cxx
src/RooFunctor1DBinding.cxx
src/RooFunctorBinding.cxx
src/RooGamma.cxx
src/RooGaussExpTails.cxx
src/RooGaussian.cxx
src/RooGaussModel.cxx
src/RooGExpModel.cxx
1 change: 1 addition & 0 deletions roofit/roofit/inc/LinkDef1.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
#pragma link C++ class RooExponential+ ;
#pragma link C++ class RooLegacyExpPoly+ ;
#pragma link C++ class RooPowerSum+ ;
#pragma link C++ class RooGaussExpTails+ ;
#pragma link C++ class RooGaussian+ ;
#pragma link C++ class RooLognormal+ ;
#pragma link C++ class RooGamma+ ;
48 changes: 48 additions & 0 deletions roofit/roofit/inc/RooGaussExpTails.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef RooFit_RooFit_RooGaussExpTails_h
#define RooFit_RooFit_RooGaussExpTails_h

#include "RooAbsPdf.h"
#include "RooRealProxy.h"

class RooAbsReal;

class RooGaussExpTails : public RooAbsPdf {
public:
RooGaussExpTails() { };
RooGaussExpTails(const char *name, const char *title,
RooAbsReal::Ref _x,
RooAbsReal::Ref _x0,
RooAbsReal::Ref _sigma,
RooAbsReal::Ref _kL,
RooAbsReal::Ref _kH
);
RooGaussExpTails(const RooGaussExpTails& other, const char* name=nullptr);
TObject* clone(const char* newname) const override {
return new RooGaussExpTails(*this,newname);
}

Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=nullptr) const override;
double analyticalIntegral(Int_t code, const char* rangeName=nullptr) const override;

RooAbsReal::Ref x() const { return *x_; }
RooAbsReal::Ref x0() const { return *x0_; }
RooAbsReal::Ref sigma() const { return *sigma_; }
RooAbsReal::Ref kL() const { return *kL_; }
RooAbsReal::Ref kH() const { return *kH_; }

protected:
double evaluate() const override;

private:
RooRealProxy x_;
RooRealProxy x0_;
RooRealProxy sigma_;
RooRealProxy kL_;
RooRealProxy kH_;

private:

ClassDefOverride(RooGaussExpTails,1) // Gaussian with double-sided exponential tails PDF, see https://arxiv.org/abs/1603.08591v1
};

#endif
110 changes: 110 additions & 0 deletions roofit/roofit/src/RooGaussExpTails.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/** \class RooGaussExpTails
\ingroup Roofit

PDF implementing a Gaussian core + double-sided exponential tail distribution
\author Souvik Das (8/1/2013) Initial implementation and
Giovanni Marchiori (30/3/2016) Implemented analytic integral
\see http://arxiv.org/pdf/1603.08591v1.pdf, https://github.com/mpuccio/RooCustomPdfs/blob/master/RooGausDExp.cxx, https://doi.org/10.1142/S0217751X14300440
\note To use the one-sided version, just set the opposite parameter k to a very large value
*/


#include "RooGaussExpTails.h"
#include "RooAbsReal.h"
#include <cmath>
#include "Math/ProbFuncMathCore.h"

ClassImp(RooGaussExpTails)


//_____________________________________________________________________________
RooGaussExpTails::RooGaussExpTails(const char *name, const char *title,
RooAbsReal::Ref _x,
RooAbsReal::Ref _x0,
RooAbsReal::Ref _sigma,
RooAbsReal::Ref _kL,
RooAbsReal::Ref _kH) :
RooAbsPdf(name,title),
x_("x","x",this,_x),
x0_("x0","x0",this,_x0),
sigma_("sigma","sigma",this,_sigma),
kL_("kL","kL",this,_kL),
kH_("kH","kH",this,_kH)
{
}


//_____________________________________________________________________________
RooGaussExpTails::RooGaussExpTails(const RooGaussExpTails& other, const char* name) :
RooAbsPdf(other,name),
x_("x",this,other.x_),
x0_("x0",this,other.x0_),
sigma_("sigma",this,other.sigma_),
kL_("kL",this,other.kL_),
kH_("kH",this,other.kH_)
{
}

////////////////////////////////////////////////////////////////////////////////

namespace {

inline double gaussianIntegral(double tmin, double tmax)
{
double m_sqrt_2_pi = 2.50662827463;//std::sqrt(TMath::TwoPi())
return m_sqrt_2_pi*(ROOT::Math::gaussian_cdf(tmax) - ROOT::Math::gaussian_cdf(tmin));
}

inline double tailIntegral(double tmin, double tmax, double k)
{
double a = std::exp(0.5*k*k)/k;
return (a*(std::exp(k*tmax)-std::exp(k*tmin)));
}

} // namespace



//_____________________________________________________________________________
Double_t RooGaussExpTails::evaluate() const
{
Double_t t=(x_-x0_)/sigma_;

if (t<=-kL_)
return exp(kL_*kL_/2.+kL_*t);
else if (t>kH_)
return exp(kH_*kH_/2.-kH_*t);
else
return exp(-0.5*t*t);
}


//_____________________________________________________________________________
Int_t RooGaussExpTails::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
{
if( matchArgs(allVars,analVars,x_) )
return 1;

return 0;
}


//_____________________________________________________________________________
Double_t RooGaussExpTails::analyticalIntegral(Int_t code, const char* rangeName) const
{
R__ASSERT(code == 1);
double result = 0;

double sig = std::abs((Double_t)sigma_);
double tmin = (x_.min(rangeName)-x0_)/sig;
double tmax = (x_.max(rangeName)-x0_)/sig;

if (tmin <= -kL_)
result += tailIntegral(tmin, TMath::Min(tmax, -kL_), kL_);
if (tmin <= kH_ && tmax > -kL_)
result += gaussianIntegral(TMath::Max(tmin, -kL_), TMath::Min(tmax, kH_));
if (tmax > kH_)
result += tailIntegral(TMath::Max(tmin, kH_), tmax, -kH_);

return sig*result;
}

Unchanged files with check annotations Beta

fOutputTensorNames = { fNY };
}
std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){

Check warning on line 38 in tmva/sofie/inc/TMVA/ROperator_Shape.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'TypeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
return input;
}
fOutputTensorNames = { fNY };
}
std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){

Check warning on line 34 in tmva/sofie/inc/TMVA/ROperator_Cast.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'TypeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
return input;
}
std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){

Check warning on line 38 in tmva/sofie/inc/TMVA/ROperator_Cast.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'ShapeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
auto ret = input; //suggest copy to compiler
return ret;
}
}
std::string Generate(std::string OpName){

Check warning on line 71 in tmva/sofie/inc/TMVA/ROperator_Cast.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'Generate' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
if (fIsOutputConstant) return "";
OpName = "op_" + OpName;
fOutputTensorNames = { fOutput };
}
std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){

Check warning on line 43 in tmva/sofie/inc/TMVA/ROperator_Concat.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'TypeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
return input;
}
// get shape of output given inputs. It is going to be called after initialized
std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> inputs){

Check warning on line 48 in tmva/sofie/inc/TMVA/ROperator_Concat.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'ShapeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
std::vector<std::vector<size_t>> ret(1);
// treat negative axis case
if (fAxis<0) {
}
}
std::string Generate(std::string OpName){

Check warning on line 194 in tmva/sofie/inc/TMVA/ROperator_Concat.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'Generate' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
if (fIsOutputConstant) return "";
OpName = "op_"+OpName;
if(fOutputShape.empty()){
}
// output type is same as input
std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){

Check warning on line 71 in tmva/sofie/inc/TMVA/ROperator_Reshape.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'TypeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
auto ret = std::vector<ETensorType>(1, input[0]);
return ret;
}
// output shape
std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){

Check warning on line 77 in tmva/sofie/inc/TMVA/ROperator_Reshape.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'ShapeInference' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
std::vector<std::vector<size_t>> ret;
auto & input_shape = input[0];
}
}
std::string Generate(std::string OpName)

Check warning on line 223 in tmva/sofie/inc/TMVA/ROperator_Reshape.hxx

GitHub Actions / mac15 ARM64 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20

'Generate' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
{
if (fIsOutputConstant) return ""; //no op for constant tensors