// Class RooGaussModel implements a RooResolutionModel that models a Gaussian
// distribution. Object of class RooGaussModel can be used
// for analytical convolutions with classes inheriting from RooAbsAnaConvPdf
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include "Riostream.h"
#include "RooGaussModel.h"
#include "RooMath.h"
#include "RooRealConstant.h"
#include "RooRandom.h"
ClassImp(RooGaussModel)
;
RooGaussModel::RooGaussModel(const char *name, const char *title, RooRealVar& xIn,
RooAbsReal& _mean, RooAbsReal& _sigma) :
RooResolutionModel(name,title,xIn),
_flatSFInt(kFALSE),
_asympInt(kFALSE),
mean("mean","Mean",this,_mean),
sigma("sigma","Width",this,_sigma),
msf("msf","Mean Scale Factor",this,(RooRealVar&)RooRealConstant::value(1)),
ssf("ssf","Sigma Scale Factor",this,(RooRealVar&)RooRealConstant::value(1))
{
}
RooGaussModel::RooGaussModel(const char *name, const char *title, RooRealVar& xIn,
RooAbsReal& _mean, RooAbsReal& _sigma,
RooAbsReal& _msSF) :
RooResolutionModel(name,title,xIn),
_flatSFInt(kFALSE),
_asympInt(kFALSE),
mean("mean","Mean",this,_mean),
sigma("sigma","Width",this,_sigma),
msf("msf","Mean Scale Factor",this,_msSF),
ssf("ssf","Sigma Scale Factor",this,_msSF)
{
}
RooGaussModel::RooGaussModel(const char *name, const char *title, RooRealVar& xIn,
RooAbsReal& _mean, RooAbsReal& _sigma,
RooAbsReal& _meanSF, RooAbsReal& _sigmaSF) :
RooResolutionModel(name,title,xIn),
_flatSFInt(kFALSE),
_asympInt(kFALSE),
mean("mean","Mean",this,_mean),
sigma("sigma","Width",this,_sigma),
msf("msf","Mean Scale Factor",this,_meanSF),
ssf("ssf","Sigma Scale Factor",this,_sigmaSF)
{
}
RooGaussModel::RooGaussModel(const RooGaussModel& other, const char* name) :
RooResolutionModel(other,name),
_flatSFInt(other._flatSFInt),
_asympInt(other._asympInt),
mean("mean",this,other.mean),
sigma("sigma",this,other.sigma),
msf("msf",this,other.msf),
ssf("ssf",this,other.ssf)
{
}
RooGaussModel::~RooGaussModel()
{
}
Int_t RooGaussModel::basisCode(const char* name) const
{
if (!TString("exp(-@0/@1)").CompareTo(name)) return expBasisPlus ;
if (!TString("exp(@0/@1)").CompareTo(name)) return expBasisMinus ;
if (!TString("exp(-abs(@0)/@1)").CompareTo(name)) return expBasisSum ;
if (!TString("exp(-@0/@1)*sin(@0*@2)").CompareTo(name)) return sinBasisPlus ;
if (!TString("exp(@0/@1)*sin(@0*@2)").CompareTo(name)) return sinBasisMinus ;
if (!TString("exp(-abs(@0)/@1)*sin(@0*@2)").CompareTo(name)) return sinBasisSum ;
if (!TString("exp(-@0/@1)*cos(@0*@2)").CompareTo(name)) return cosBasisPlus ;
if (!TString("exp(@0/@1)*cos(@0*@2)").CompareTo(name)) return cosBasisMinus ;
if (!TString("exp(-abs(@0)/@1)*cos(@0*@2)").CompareTo(name)) return cosBasisSum ;
if (!TString("(@0/@1)*exp(-@0/@1)").CompareTo(name)) return linBasisPlus ;
if (!TString("(@0/@1)*(@0/@1)*exp(-@0/@1)").CompareTo(name)) return quadBasisPlus ;
if (!TString("exp(-@0/@1)*cosh(@0*@2/2)").CompareTo(name)) return coshBasisPlus;
if (!TString("exp(@0/@1)*cosh(@0*@2/2)").CompareTo(name)) return coshBasisMinus;
if (!TString("exp(-abs(@0)/@1)*cosh(@0*@2/2)").CompareTo(name)) return coshBasisSum;
if (!TString("exp(-@0/@1)*sinh(@0*@2/2)").CompareTo(name)) return sinhBasisPlus;
if (!TString("exp(@0/@1)*sinh(@0*@2/2)").CompareTo(name)) return sinhBasisMinus;
if (!TString("exp(-abs(@0)/@1)*sinh(@0*@2/2)").CompareTo(name)) return sinhBasisSum;
return 0 ;
}
Double_t RooGaussModel::evaluate() const
{
static Double_t root2(sqrt(2.)) ;
static Double_t root2pi(sqrt(2*atan2(0.,-1.))) ;
static Double_t rootpi(sqrt(atan2(0.,-1.))) ;
BasisType basisType = (BasisType)( (_basisCode == 0) ? 0 : (_basisCode/10) + 1 );
BasisSign basisSign = (BasisSign)( _basisCode - 10*(basisType-1) - 2 ) ;
Double_t tau = (_basisCode!=noBasis)?((RooAbsReal*)basis().getParameter(1))->getVal():0 ;
if (basisType == coshBasis && _basisCode!=noBasis ) {
Double_t dGamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
if (dGamma==0) basisType = expBasis;
}
if (basisType==none || ((basisType==expBasis || basisType==cosBasis) && tau==0.)) {
Double_t xprime = (x-(mean*msf))/(sigma*ssf) ;
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 1st form" << endl ;
Double_t result = exp(-0.5*xprime*xprime)/(sigma*ssf*root2pi) ;
if (_basisCode!=0 && basisSign==Both) result *= 2 ;
return result ;
}
if (tau==0) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 2nd form" << endl ;
return 0. ;
}
Double_t omega = (basisType==sinBasis || basisType==cosBasis)
? ((RooAbsReal*)basis().getParameter(2))->getVal() : 0 ;
Double_t xprime = (x-(mean*msf))/tau ;
Double_t c = (sigma*ssf)/(root2*tau) ;
Double_t u = xprime/(2*c) ;
if (basisType==expBasis || (basisType==cosBasis && omega==0.)) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 3d form tau=" << tau << endl ;
Double_t result(0) ;
if (basisSign!=Minus) result += exp(-xprime+c*c) * RooMath::erfc(-u+c) ;
if (basisSign!=Plus) result += exp(xprime+c*c) * RooMath::erfc(u+c) ;
return result ;
}
Double_t wt = omega *tau ;
if (basisType==sinBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 4th form omega = "
<< omega << ", tau = " << tau << endl ;
Double_t result(0) ;
if (wt==0.) return result ;
if (basisSign!=Minus) result += -1*evalCerfIm(-wt,-u,c) ;
if (basisSign!=Plus) result += -1*evalCerfIm(wt,u,c) ;
return result ;
}
if (basisType==cosBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName()
<< ") 5th form omega = " << omega << ", tau = " << tau << endl ;
Double_t result(0) ;
if (basisSign!=Minus) result += evalCerfRe(-wt,-u,c) ;
if (basisSign!=Plus) result += evalCerfRe(wt,u,c) ;
return result ;
}
if (basisType==linBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName()
<< ") 6th form tau = " << tau << endl ;
assert(basisSign==Plus);
Double_t f0 = exp(-xprime+c*c) * RooMath::erfc(-u+c);
Double_t f1 = exp(-u*u);
return (xprime - 2*c*c)*f0 + (2*c/rootpi)*f1 ;
}
if (basisType==quadBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName()
<< ") 7th form tau = " << tau << endl ;
assert(basisSign==Plus);
Double_t f0 = exp(-xprime+c*c) * RooMath::erfc(-u+c);
Double_t f1 = exp(-u*u);
Double_t x2c2 = xprime - 2*c*c;
return ( x2c2*x2c2*f0 + (2*c/rootpi)*x2c2*f1 + 2*c*c*f0 );
}
if (basisType==coshBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName()
<< ") 8th form tau = " << tau << endl ;
Double_t dgamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
Double_t tau1 = 1/(1/tau-dgamma/2) ;
Double_t tau2 = 1/(1/tau+dgamma/2) ;
Double_t xprime1 = (x-(mean*msf))/tau1 ;
Double_t c1 = (sigma*ssf)/(root2*tau1) ;
Double_t u1 = xprime1/(2*c1) ;
Double_t xprime2 = (x-(mean*msf))/tau2 ;
Double_t c2 = (sigma*ssf)/(root2*tau2) ;
Double_t u2 = xprime2/(2*c2) ;
Double_t result(0);
if (basisSign!=Minus) result += 0.5*(evalCerfRe(-u1,c1)+evalCerfRe(-u2,c2)) ;
if (basisSign!=Plus) result += 0.5*(evalCerfRe( u1,c1)+evalCerfRe( u2,c2)) ;
return result ;
}
if (basisType==sinhBasis) {
if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName()
<< ") 9th form tau = " << tau << endl ;
Double_t dgamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
Double_t tau1 = 1/(1/tau-dgamma/2) ;
Double_t tau2 = 1/(1/tau+dgamma/2) ;
Double_t xprime1 = (x-(mean*msf))/tau1 ;
Double_t c1 = (sigma*ssf)/(root2*tau1) ;
Double_t u1 = xprime1/(2*c1) ;
Double_t xprime2 = (x-(mean*msf))/tau2 ;
Double_t c2 = (sigma*ssf)/(root2*tau2) ;
Double_t u2 = xprime2/(2*c2) ;
Double_t result(0);
if (basisSign!=Minus) result += 0.5*(evalCerfRe(-u1,c1)-evalCerfRe(-u2,c2)) ;
if (basisSign!=Plus) result += 0.5*(evalCerfRe( u2,c2)-evalCerfRe( u1,c1)) ;
return result ;
}
assert(0) ;
return 0 ;
}
Int_t RooGaussModel::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* ) const
{
switch(_basisCode) {
case noBasis:
if (matchArgs(allVars,analVars,convVar())) return 1 ;
break ;
case expBasisPlus:
case expBasisMinus:
case expBasisSum:
case sinBasisPlus:
case sinBasisMinus:
case sinBasisSum:
case cosBasisPlus:
case cosBasisMinus:
case cosBasisSum:
case linBasisPlus:
case quadBasisPlus:
case coshBasisMinus:
case coshBasisPlus:
case coshBasisSum:
case sinhBasisMinus:
case sinhBasisPlus:
case sinhBasisSum:
if (_flatSFInt) {
if (matchArgs(allVars,analVars,RooArgSet(convVar(),ssf.arg()))) {
return 2 ;
}
}
if (matchArgs(allVars,analVars,convVar())) return 1 ;
break ;
}
return 0 ;
}
Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) const
{
static Double_t root2 = sqrt(2.) ;
static Double_t rootpi = sqrt(atan2(0.0,-1.0));
Double_t ssfInt(1.0) ;
assert(code==1||code==2) ;
if (code==2) {
ssfInt = (ssf.max(rangeName)-ssf.min(rangeName)) ;
}
BasisType basisType = (BasisType)( (_basisCode == 0) ? 0 : (_basisCode/10) + 1 );
BasisSign basisSign = (BasisSign)( _basisCode - 10*(basisType-1) - 2 ) ;
Double_t tau = (_basisCode!=noBasis)?((RooAbsReal*)basis().getParameter(1))->getVal():0 ;
if (basisType == coshBasis && _basisCode!=noBasis ) {
Double_t dGamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
if (dGamma==0) basisType = expBasis;
}
if (basisType==none || ((basisType==expBasis || basisType==cosBasis) && tau==0.)) {
Double_t xscale = root2*(sigma*ssf);
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 1st form" << endl ;
Double_t xpmin = (x.min(rangeName)-(mean*msf))/xscale ;
Double_t xpmax = (x.max(rangeName)-(mean*msf))/xscale ;
Double_t result ;
if (_asympInt) {
result = 1.0 ;
} else {
if (xpmin<-6 && xpmax>6) {
result = 1.0 ;
} else {
result = 0.5*(RooMath::erf(xpmax)-RooMath::erf(xpmin)) ;
}
}
if (_basisCode!=0 && basisSign==Both) result *= 2 ;
return result*ssfInt ;
}
Double_t omega = ((basisType==sinBasis)||(basisType==cosBasis)) ?
((RooAbsReal*)basis().getParameter(2))->getVal() : 0 ;
if (tau==0) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 2nd form" << endl ;
return 0. ;
}
Double_t c = (sigma*ssf)/(root2*tau) ;
Double_t xpmin = (x.min(rangeName)-(mean*msf))/tau ;
Double_t xpmax = (x.max(rangeName)-(mean*msf))/tau ;
Double_t umin = xpmin/(2*c) ;
Double_t umax = xpmax/(2*c) ;
if (basisType==expBasis || (basisType==cosBasis && omega==0.)) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 3d form tau=" << tau << endl ;
Double_t result(0) ;
if (_asympInt) {
if (basisSign!=Minus) result += 2 * tau ;
if (basisSign!=Plus) result += 2 * tau ;
} else {
if (basisSign!=Minus) result += -1 * tau * ( RooMath::erf(-umax) - RooMath::erf(-umin) +
exp(c*c) * ( exp(-xpmax)*RooMath::erfc(-umax+c)
- exp(-xpmin)*RooMath::erfc(-umin+c) )) ;
if (basisSign!=Plus) result += tau * ( RooMath::erf(umax) - RooMath::erf(umin) +
exp(c*c) * ( exp(xpmax)*RooMath::erfc(umax+c)
- exp(xpmin)*RooMath::erfc(umin+c) )) ;
}
return result*ssfInt ;
}
Double_t wt = omega * tau ;
if (basisType==sinBasis) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 4th form omega = "
<< omega << ", tau = " << tau << endl ;
Double_t result(0) ;
if (wt==0) return result*ssfInt ;
if (basisSign!=Minus) {
RooComplex evalDif(evalCerf(-wt,-umax,c) - evalCerf(-wt,-umin,c)) ;
result += -tau/(1+wt*wt) * ( -evalDif.im() + wt*evalDif.re() - -wt*(RooMath::erf(-umax) - RooMath::erf(-umin)) ) ;
}
if (basisSign!=Plus) {
RooComplex evalDif(evalCerf(wt,umax,c) - evalCerf(wt,umin,c)) ;
result += tau/(1+wt*wt) * ( -evalDif.im() + -wt*evalDif.re() - wt*(RooMath::erf(umax) - RooMath::erf(umin)) ) ;
}
return result*ssfInt ;
}
if (basisType==cosBasis) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName()
<< ") 5th form omega = " << omega << ", tau = " << tau << endl ;
Double_t result(0) ;
if (basisSign!=Minus) {
RooComplex evalDif(evalCerf(-wt,-umax,c) - evalCerf(-wt,-umin,c)) ;
result += -tau/(1+wt*wt) * ( evalDif.re() + wt*evalDif.im() + RooMath::erf(-umax) - RooMath::erf(-umin) ) ;
}
if (basisSign!=Plus) {
RooComplex evalDif(evalCerf(wt,umax,c) - evalCerf(wt,umin,c)) ;
result += tau/(1+wt*wt) * ( evalDif.re() + -wt*evalDif.im() + RooMath::erf(umax) - RooMath::erf(umin) ) ;
}
return result*ssfInt ;
}
if (basisType==linBasis) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName()
<< ") 6th form tau=" << tau << endl ;
Double_t f0 = RooMath::erf(-umax) - RooMath::erf(-umin);
Double_t f1 = exp(-umax*umax) - exp(-umin*umin);
Double_t tmp1 = exp(-xpmax)*RooMath::erfc(-umax + c);
Double_t tmp2 = exp(-xpmin)*RooMath::erfc(-umin + c);
Double_t f2 = tmp1 - tmp2;
Double_t f3 = xpmax*tmp1 - xpmin*tmp2;
Double_t expc2 = exp(c*c);
return -tau*( f0 +
(2*c/rootpi)*f1 +
(1 - 2*c*c)*expc2*f2 +
expc2*f3
)*ssfInt;
}
if (basisType==quadBasis) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName()
<< ") 7th form tau=" << tau << endl ;
Double_t f0 = RooMath::erf(-umax) - RooMath::erf(-umin);
Double_t tmpA1 = exp(-umax*umax);
Double_t tmpA2 = exp(-umin*umin);
Double_t f1 = tmpA1 - tmpA2;
Double_t f2 = umax*tmpA1 - umin*tmpA2;
Double_t tmpB1 = exp(-xpmax)*RooMath::erfc(-umax + c);
Double_t tmpB2 = exp(-xpmin)*RooMath::erfc(-umin + c);
Double_t f3 = tmpB1 - tmpB2;
Double_t f4 = xpmax*tmpB1 - xpmin*tmpB2;
Double_t f5 = xpmax*xpmax*tmpB1 - xpmin*xpmin*tmpB2;
Double_t expc2 = exp(c*c);
return -tau*( 2*f0 +
(4*c/rootpi)*((1-c*c)*f1 + c*f2) +
(2*c*c*(2*c*c-1) + 2)*expc2*f3 - (4*c*c-2)*expc2*f4 + expc2*f5
)*ssfInt;
}
if (basisType==coshBasis) {
if (verboseEval()>0) {cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 8th form tau=" << tau << endl ; }
Double_t dgamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
Double_t tau1 = 1/(1/tau-dgamma/2) ;
Double_t tau2 = 1/(1/tau+dgamma/2) ;
Double_t c1 = (sigma*ssf)/(root2*tau1) ;
Double_t xpmin1 = (x.min(rangeName)-(mean*msf))/tau1 ;
Double_t xpmax1 = (x.max(rangeName)-(mean*msf))/tau1 ;
Double_t umin1 = xpmin1/(2*c1) ;
Double_t umax1 = xpmax1/(2*c1) ;
Double_t c2 = (sigma*ssf)/(root2*tau2) ;
Double_t xpmin2 = (x.min(rangeName)-(mean*msf))/tau2 ;
Double_t xpmax2 = (x.max(rangeName)-(mean*msf))/tau2 ;
Double_t umin2 = xpmin2/(2*c2) ;
Double_t umax2 = xpmax2/(2*c2) ;
Double_t result(0) ;
if (basisSign!=Minus) result += 0.5*(evalCerfInt(+1,tau1,-umin1,-umax1,c1)+
evalCerfInt(+1,tau2,-umin2,-umax2,c2));
if (basisSign!=Plus) result += 0.5*(evalCerfInt(-1,tau1,umin1,umax1,c1)+
evalCerfInt(-1,tau2,umin2,umax2,c2));
return result*ssfInt ;
}
if (basisType==sinhBasis) {
if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 9th form tau=" << tau << endl ;
Double_t dgamma = ((RooAbsReal*)basis().getParameter(2))->getVal();
Double_t tau1 = 1/(1/tau-dgamma/2) ;
Double_t tau2 = 1/(1/tau+dgamma/2) ;
Double_t c1 = (sigma*ssf)/(root2*tau1) ;
Double_t xpmin1 = (x.min(rangeName)-(mean*msf))/tau1 ;
Double_t xpmax1 = (x.max(rangeName)-(mean*msf))/tau1 ;
Double_t umin1 = xpmin1/(2*c1) ;
Double_t umax1 = xpmax1/(2*c1) ;
Double_t c2 = (sigma*ssf)/(root2*tau2) ;
Double_t xpmin2 = (x.min(rangeName)-(mean*msf))/tau2 ;
Double_t xpmax2 = (x.max(rangeName)-(mean*msf))/tau2 ;
Double_t umin2 = xpmin2/(2*c2) ;
Double_t umax2 = xpmax2/(2*c2) ;
Double_t result(0) ;
if (basisSign!=Minus) result += 0.5*(evalCerfInt(+1,tau1,-umin1,-umax1,c1)-
evalCerfInt(+1,tau2,-umin2,-umax2,c2));
if (basisSign!=Plus) result += 0.5*(evalCerfInt(-1,tau2,umin2,umax2,c2)-
evalCerfInt(-1,tau1,umin1,umax1,c1));
return result*ssfInt ;
}
assert(0) ;
return 0 ;
}
RooComplex RooGaussModel::evalCerfApprox(Double_t swt, Double_t u, Double_t c) const
{
static Double_t rootpi= sqrt(atan2(0.,-1.));
RooComplex z(swt*c,u+c);
RooComplex zc(u+c,-swt*c);
RooComplex zsq= z*z;
RooComplex v= -zsq - u*u;
return v.exp()*(-zsq.exp()/(zc*rootpi) + 1)*2 ;
}
RooComplex RooGaussModel::evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
{
RooComplex diff;
if (_asympInt) {
diff = RooComplex(2,0) ;
} else {
diff = RooComplex(sign,0.)*(evalCerf(wt,umin,c) - evalCerf(wt,umax,c) + RooMath::erf(umin) - RooMath::erf(umax));
}
return RooComplex(tau/(1.+wt*wt),0)*RooComplex(1,wt)*diff;
}
Double_t RooGaussModel::evalCerfInt(Double_t sign, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
{
Double_t diff;
if (_asympInt) {
diff = 2. ;
} else {
if ((umin<-8 && umax>8)||(umax<-8 && umin>8)) {
diff = 2. ;
} else {
diff = sign*(evalCerfRe(umin,c) - evalCerfRe(umax,c) + RooMath::erf(umin) - RooMath::erf(umax));
}
}
return tau*diff;
}
Int_t RooGaussModel::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t ) const
{
if (matchArgs(directVars,generateVars,x)) return 1 ;
return 0 ;
}
void RooGaussModel::generateEvent(Int_t code)
{
assert(code==1) ;
Double_t xgen ;
while(1) {
xgen = RooRandom::randomGenerator()->Gaus((mean*msf),(sigma*ssf));
if (xgen<x.max() && xgen>x.min()) {
x = xgen ;
return ;
}
}
}
Last change: Wed Jun 25 08:32:59 2008
Last generated: 2008-06-25 08:32
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.