68 ClassImp(RooRealSumPdf);
71 Bool_t RooRealSumPdf::_doFloorGlobal = kFALSE ;
77 RooRealSumPdf::RooRealSumPdf()
88 RooRealSumPdf::RooRealSumPdf(
const char *name,
const char *title) :
89 RooAbsPdf(name,title),
91 _funcList(
"!funcList",
"List of functions",this),
92 _coefList(
"!coefList",
"List of coefficients",this),
106 RooRealSumPdf::RooRealSumPdf(
const char *name,
const char *title,
107 RooAbsReal& func1, RooAbsReal& func2, RooAbsReal& coef1) :
108 RooAbsPdf(name,title),
109 _normIntMgr(this,10),
110 _funcList(
"!funcList",
"List of functions",this),
111 _coefList(
"!coefList",
"List of coefficients",this),
117 _funcList.add(func1) ;
118 _funcList.add(func2) ;
119 _coefList.add(coef1) ;
149 RooRealSumPdf::RooRealSumPdf(
const char *name,
const char *title,
150 const RooArgList& inFuncList,
const RooArgList& inCoefList, Bool_t extended) :
151 RooAbsPdf(name,title),
152 _normIntMgr(this,10),
153 _funcList(
"!funcList",
"List of functions",this),
154 _coefList(
"!coefList",
"List of coefficients",this),
158 if (!(inFuncList.getSize()==inCoefList.getSize()+1 || inFuncList.getSize()==inCoefList.getSize())) {
159 coutE(InputArguments) <<
"RooRealSumPdf::RooRealSumPdf(" << GetName()
160 <<
") number of pdfs and coefficients inconsistent, must have Nfunc=Ncoef or Nfunc=Ncoef+1" << endl ;
165 for (
unsigned int i = 0; i < inCoefList.size(); ++i) {
166 const auto& func = inFuncList[i];
167 const auto& coef = inCoefList[i];
169 if (!dynamic_cast<const RooAbsReal*>(&coef)) {
170 coutW(InputArguments) <<
"RooRealSumPdf::RooRealSumPdf(" << GetName() <<
") coefficient " << coef.GetName() <<
" is not of type RooAbsReal, ignored" << endl ;
173 if (!dynamic_cast<const RooAbsReal*>(&func)) {
174 coutW(InputArguments) <<
"RooRealSumPdf::RooRealSumPdf(" << GetName() <<
") func " << func.GetName() <<
" is not of type RooAbsReal, ignored" << endl ;
177 _funcList.add(func) ;
178 _coefList.add(coef) ;
181 if (inFuncList.size() == inCoefList.size() + 1) {
182 const auto& func = inFuncList[inFuncList.size()-1];
183 if (!dynamic_cast<const RooAbsReal*>(&func)) {
184 coutE(InputArguments) <<
"RooRealSumPdf::RooRealSumPdf(" << GetName() <<
") last func " << func.GetName() <<
" is not of type RooAbsReal, fatal error" << endl ;
198 RooRealSumPdf::RooRealSumPdf(
const RooRealSumPdf& other,
const char* name) :
199 RooAbsPdf(other,name),
200 _normIntMgr(other._normIntMgr,this),
201 _funcList(
"!funcList",this,other._funcList),
202 _coefList(
"!coefList",this,other._coefList),
203 _extended(other._extended),
204 _doFloor(other._doFloor)
214 RooRealSumPdf::~RooRealSumPdf()
225 RooAbsPdf::ExtendMode RooRealSumPdf::extendMode()
const
227 return (_extended && (_funcList.getSize()==_coefList.getSize())) ? CanBeExtended : CanNotBeExtended ;
236 Double_t RooRealSumPdf::evaluate()
const
243 Double_t lastCoef(1) ;
244 auto funcIt = _funcList.begin();
245 for (
const auto coefArg : _coefList) {
246 assert(funcIt != _funcList.end());
247 auto func =
static_cast<const RooAbsReal*
>(*funcIt++);
248 auto coef =
static_cast<const RooAbsReal*
>(coefArg);
250 Double_t coefVal = coef->getVal() ;
252 cxcoutD(Eval) <<
"RooRealSumPdf::eval(" << GetName() <<
") coefVal = " << coefVal <<
" funcVal = " << func->IsA()->GetName() <<
"::" << func->GetName() <<
" = " << func->getVal() << endl ;
253 if (func->isSelectedComp()) {
254 value += func->getVal()*coefVal ;
256 lastCoef -= coef->getVal() ;
260 if (!haveLastCoef()) {
261 assert(funcIt != _funcList.end());
263 auto func =
static_cast<const RooAbsReal*
>(*funcIt);
264 if (func->isSelectedComp()) {
265 value += func->getVal()*lastCoef ;
268 cxcoutD(Eval) <<
"RooRealSumPdf::eval(" << GetName() <<
") lastCoef = " << lastCoef <<
" funcVal = " << func->getVal() << endl ;
271 if (lastCoef<0 || lastCoef>1) {
272 coutW(Eval) <<
"RooRealSumPdf::evaluate(" << GetName()
273 <<
") WARNING: sum of FUNC coefficients not in range [0-1], value="
274 << 1-lastCoef <<
". This means that the PDF is not properly normalised. If the PDF was meant to be extended, provide as many coefficients as functions." << endl ;
279 if (value<0 && (_doFloor || _doFloorGlobal)) {
297 Bool_t RooRealSumPdf::checkObservables(
const RooArgSet* nset)
const
301 for (
unsigned int i=0; i < _coefList.size(); ++i) {
302 const auto& coef = _coefList[i];
303 const auto& func = _funcList[i];
305 if (func.observableOverlaps(nset, coef)) {
306 coutE(InputArguments) <<
"RooRealSumPdf::checkObservables(" << GetName() <<
"): ERROR: coefficient " << coef.GetName()
307 <<
" and FUNC " << func.GetName() <<
" have one or more observables in common" << endl ;
310 if (coef.dependsOn(*nset)) {
311 coutE(InputArguments) <<
"RooRealPdf::checkObservables(" << GetName() <<
"): ERROR coefficient " << coef.GetName()
312 <<
" depends on one or more of the following observables" ; nset->Print(
"1") ;
326 Int_t RooRealSumPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
327 const RooArgSet* normSet2,
const char* rangeName)
const
330 if (allVars.getSize()==0)
return 0 ;
331 if (_forceNumInt)
return 0 ;
334 analVars.add(allVars) ;
335 RooArgSet* normSet = normSet2 ? getObservables(normSet2) : 0 ;
339 Int_t sterileIdx(-1) ;
340 CacheElem* cache = (CacheElem*) _normIntMgr.getObj(normSet,&analVars,&sterileIdx,RooNameReg::ptr(rangeName)) ;
343 return _normIntMgr.lastIndex()+1 ;
347 cache =
new CacheElem ;
350 for (
const auto elm : _funcList) {
351 const auto func =
static_cast<RooAbsReal*
>(elm);
353 RooAbsReal* funcInt = func->createIntegral(analVars,rangeName) ;
354 if(funcInt->InheritsFrom(RooRealIntegral::Class())) ((RooRealIntegral*)funcInt)->setAllowComponentSelection(
true);
355 cache->_funcIntList.addOwned(*funcInt) ;
356 if (normSet && normSet->getSize()>0) {
357 RooAbsReal* funcNorm = func->createIntegral(*normSet) ;
358 cache->_funcNormList.addOwned(*funcNorm) ;
363 Int_t code = _normIntMgr.setObj(normSet,&analVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName)) ;
380 Double_t RooRealSumPdf::analyticalIntegralWN(Int_t code,
const RooArgSet* normSet2,
const char* rangeName)
const
383 if (code==0)
return getVal(normSet2) ;
387 CacheElem* cache = (CacheElem*) _normIntMgr.getObjByIndex(code-1) ;
390 std::unique_ptr<RooArgSet> vars( getParameters(RooArgSet()) );
391 std::unique_ptr<RooArgSet> iset( _normIntMgr.nameSet2ByIndex(code-1)->select(*vars) );
392 std::unique_ptr<RooArgSet> nset( _normIntMgr.nameSet1ByIndex(code-1)->select(*vars) );
394 Int_t code2 = getAnalyticalIntegralWN(*iset,dummy,nset.get(),rangeName);
395 R__ASSERT(code==code2);
396 cache = (CacheElem*) _normIntMgr.getObjByIndex(code-1) ;
403 Double_t lastCoef(1) ;
404 auto funcIt = _funcList.begin();
405 auto funcIntIt = cache->_funcIntList.begin();
406 for (
const auto coefArg : _coefList) {
407 assert(funcIt != _funcList.end());
408 const auto coef =
static_cast<const RooAbsReal*
>(coefArg);
409 const auto func =
static_cast<const RooAbsReal*
>(*funcIt++);
410 const auto funcInt =
static_cast<RooAbsReal*
>(*funcIntIt++);
412 Double_t coefVal = coef->getVal(normSet2) ;
415 if (normSet2 ==0 || func->isSelectedComp()) {
417 value += funcInt->getVal()*coefVal ;
419 lastCoef -= coef->getVal(normSet2) ;
423 if (!haveLastCoef()) {
425 const auto func =
static_cast<const RooAbsReal*
>(*funcIt);
426 const auto funcInt =
static_cast<RooAbsReal*
>(*funcIntIt);
429 if (normSet2 ==0 || func->isSelectedComp()) {
431 value += funcInt->getVal()*lastCoef ;
435 if (lastCoef<0 || lastCoef>1) {
436 coutW(Eval) <<
"RooRealSumPdf::evaluate(" << GetName()
437 <<
" WARNING: sum of FUNC coefficients not in range [0-1], value="
438 << 1-lastCoef << endl ;
442 Double_t normVal(1) ;
443 if (normSet2 && normSet2->getSize()>0) {
447 auto funcNormIter = cache->_funcNormList.begin();
448 for (
const auto coefAsArg : _coefList) {
449 auto coef =
static_cast<RooAbsReal*
>(coefAsArg);
450 auto funcNorm =
static_cast<RooAbsReal*
>(*funcNormIter++);
452 Double_t coefVal = coef->getVal(normSet2);
455 normVal += funcNorm->getVal()*coefVal ;
460 if (!haveLastCoef()) {
461 auto funcNorm =
static_cast<RooAbsReal*
>(*funcNormIter);
464 normVal += funcNorm->getVal()*lastCoef;
468 return value / normVal;
474 Double_t RooRealSumPdf::expectedEvents(
const RooArgSet* nset)
const
476 Double_t n = getNorm(nset) ;
478 logEvalError(
"Expected number of events is negative") ;
486 std::list<Double_t>* RooRealSumPdf::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi)
const
488 list<Double_t>* sumBinB = 0 ;
489 Bool_t needClean(kFALSE) ;
492 for (
const auto elm : _funcList) {
493 auto func =
static_cast<RooAbsReal*
>(elm);
495 list<Double_t>* funcBinB = func->binBoundaries(obs,xlo,xhi) ;
504 list<Double_t>* newSumBinB =
new list<Double_t>(sumBinB->size()+funcBinB->size()) ;
507 merge(funcBinB->begin(),funcBinB->end(),sumBinB->begin(),sumBinB->end(),newSumBinB->begin()) ;
512 sumBinB = newSumBinB ;
520 list<Double_t>::iterator new_end = unique(sumBinB->begin(),sumBinB->end()) ;
521 sumBinB->erase(new_end,sumBinB->end()) ;
530 Bool_t RooRealSumPdf::isBinnedDistribution(
const RooArgSet& obs)
const
534 for (
const auto elm : _funcList) {
535 auto func =
static_cast<RooAbsReal*
>(elm);
537 if (func->dependsOn(obs) && !func->isBinnedDistribution(obs)) {
551 std::list<Double_t>* RooRealSumPdf::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi)
const
553 list<Double_t>* sumHint = 0 ;
554 Bool_t needClean(kFALSE) ;
557 for (
const auto elm : _funcList) {
558 auto func =
static_cast<RooAbsReal*
>(elm);
560 list<Double_t>* funcHint = func->plotSamplingHint(obs,xlo,xhi) ;
571 list<Double_t>* newSumHint =
new list<Double_t>(sumHint->size()+funcHint->size()) ;
574 merge(funcHint->begin(),funcHint->end(),sumHint->begin(),sumHint->end(),newSumHint->begin()) ;
578 sumHint = newSumHint ;
586 list<Double_t>::iterator new_end = unique(sumHint->begin(),sumHint->end()) ;
587 sumHint->erase(new_end,sumHint->end()) ;
599 void RooRealSumPdf::setCacheAndTrackHints(RooArgSet& trackNodes)
601 for (
const auto sarg : _funcList) {
602 if (sarg->canNodeBeCached()==Always) {
603 trackNodes.add(*sarg) ;
615 void RooRealSumPdf::printMetaArgs(ostream& os)
const
618 Bool_t first(kTRUE) ;
620 if (_coefList.getSize()!=0) {
621 auto funcIter = _funcList.begin();
623 for (
const auto coef : _coefList) {
629 const auto func = *(funcIter++);
630 os << coef->GetName() <<
" * " << func->GetName();
633 if (funcIter != _funcList.end()) {
634 os <<
" + [%] * " << (*funcIter)->GetName() ;
638 for (
const auto func : _funcList) {
644 os << func->GetName() ;