66 ClassImp(RooAddModel);
72 RooAddModel::RooAddModel() :
73 _refCoefNorm(
"!refCoefNorm",
"Reference coefficient normalization set",this,kFALSE,kFALSE),
78 _pdfIter = _pdfList.createIterator() ;
79 _coefIter = _coefList.createIterator() ;
81 _coefCache =
new Double_t[10] ;
82 _coefErrCount = _errorCount ;
95 RooAddModel::RooAddModel(
const char *name,
const char *title,
const RooArgList& inPdfList,
const RooArgList& inCoefList, Bool_t ownPdfList) :
96 RooResolutionModel(name,title,((RooResolutionModel*)inPdfList.at(0))->convVar()),
97 _refCoefNorm(
"!refCoefNorm",
"Reference coefficient normalization set",this,kFALSE,kFALSE),
99 _projectCoefs(kFALSE),
100 _projCacheMgr(this,10),
101 _intCacheMgr(this,10),
103 _pdfList(
"!pdfs",
"List of PDFs",this),
104 _coefList(
"!coefficients",
"List of coefficients",this),
105 _haveLastCoef(kFALSE),
106 _allExtendable(kFALSE)
108 if (inPdfList.getSize()>inCoefList.getSize()+1) {
109 coutE(InputArguments) <<
"RooAddModel::RooAddModel(" << GetName()
110 <<
") number of pdfs and coefficients inconsistent, must have Npdf=Ncoef or Npdf=Ncoef+1" << endl ;
114 _pdfIter = _pdfList.createIterator() ;
115 _coefIter = _coefList.createIterator() ;
118 TIterator* pdfIter = inPdfList.createIterator() ;
119 TIterator* coefIter = inCoefList.createIterator() ;
123 while((coef = (RooAbsPdf*)coefIter->Next())) {
124 pdf = (RooAbsPdf*) pdfIter->Next() ;
126 coutE(InputArguments) <<
"RooAddModel::RooAddModel(" << GetName()
127 <<
") number of pdfs and coefficients inconsistent, must have Npdf=Ncoef or Npdf=Ncoef+1" << endl ;
130 if (!dynamic_cast<RooAbsReal*>(coef)) {
131 coutE(InputArguments) <<
"RooAddModel::RooAddModel(" << GetName() <<
") coefficient " << coef->GetName() <<
" is not of type RooAbsReal, ignored" << endl ;
134 if (!dynamic_cast<RooAbsReal*>(pdf)) {
135 coutE(InputArguments) <<
"RooAddModel::RooAddModel(" << GetName() <<
") pdf " << pdf->GetName() <<
" is not of type RooAbsPdf, ignored" << endl ;
139 _coefList.add(*coef) ;
142 pdf = (RooAbsPdf*) pdfIter->Next() ;
144 if (!dynamic_cast<RooAbsReal*>(pdf)) {
145 coutE(InputArguments) <<
"RooAddModel::RooAddModel(" << GetName() <<
") last pdf " << coef->GetName() <<
" is not of type RooAbsPdf, fatal error" << endl ;
150 _haveLastCoef=kTRUE ;
156 _coefCache =
new Double_t[_pdfList.getSize()] ;
157 _coefErrCount = _errorCount ;
160 _ownedComps.addOwned(_pdfList) ;
170 RooAddModel::RooAddModel(
const RooAddModel& other,
const char* name) :
171 RooResolutionModel(other,name),
172 _refCoefNorm(
"!refCoefNorm",this,other._refCoefNorm),
173 _refCoefRangeName((TNamed*)other._refCoefRangeName),
174 _projectCoefs(other._projectCoefs),
175 _projCacheMgr(other._projCacheMgr,this),
176 _intCacheMgr(other._intCacheMgr,this),
177 _codeReg(other._codeReg),
178 _pdfList(
"!pdfs",this,other._pdfList),
179 _coefList(
"!coefficients",this,other._coefList),
180 _haveLastCoef(other._haveLastCoef),
181 _allExtendable(other._allExtendable)
183 _pdfIter = _pdfList.createIterator() ;
184 _coefIter = _coefList.createIterator() ;
185 _coefCache =
new Double_t[_pdfList.getSize()] ;
186 _coefErrCount = _errorCount ;
194 RooAddModel::~RooAddModel()
199 if (_coefCache)
delete[] _coefCache ;
214 void RooAddModel::fixCoefNormalization(
const RooArgSet& refCoefNorm)
216 if (refCoefNorm.getSize()==0) {
217 _projectCoefs = kFALSE ;
220 _projectCoefs = kTRUE ;
222 _refCoefNorm.removeAll() ;
223 _refCoefNorm.add(refCoefNorm) ;
225 _projCacheMgr.reset() ;
241 void RooAddModel::fixCoefRange(
const char* rangeName)
243 _refCoefRangeName = (TNamed*)RooNameReg::ptr(rangeName) ;
244 if (_refCoefRangeName) _projectCoefs = kTRUE ;
256 RooResolutionModel* RooAddModel::convolution(RooFormulaVar* inBasis, RooAbsArg* owner)
const
259 if (inBasis->getParameter(0) != x.absArg()) {
260 coutE(InputArguments) <<
"RooAddModel::convolution(" << GetName()
261 <<
") convolution parameter of basis function and PDF don't match" << endl ;
262 ccoutE(InputArguments) <<
"basis->findServer(0) = " << inBasis->findServer(0) <<
" " << inBasis->findServer(0)->GetName() << endl ;
263 ccoutE(InputArguments) <<
"x.absArg() = " << x.absArg() <<
" " << x.absArg()->GetName() << endl ;
264 inBasis->Print(
"v") ;
268 TString newName(GetName()) ;
269 newName.Append(
"_conv_") ;
270 newName.Append(inBasis->GetName()) ;
271 newName.Append(
"_[") ;
272 newName.Append(owner->GetName()) ;
273 newName.Append(
"]") ;
275 TString newTitle(GetTitle()) ;
276 newTitle.Append(
" convoluted with basis function ") ;
277 newTitle.Append(inBasis->GetName()) ;
280 RooResolutionModel* model ;
281 RooArgList modelList ;
282 while((model = (RooResolutionModel*)_pdfIter->Next())) {
284 RooResolutionModel* conv = model->convolution(inBasis,owner) ;
285 modelList.add(*conv) ;
290 RooArgList theCoefList ;
291 while((coef = (RooAbsReal*)_coefIter->Next())) {
292 theCoefList.add(*coef) ;
295 RooAddModel* convSum =
new RooAddModel(newName,newTitle,modelList,theCoefList,kTRUE) ;
296 for (std::set<std::string>::const_iterator attrIt = _boolAttrib.begin();
297 attrIt != _boolAttrib.end(); ++attrIt) {
298 convSum->setAttribute((*attrIt).c_str()) ;
300 for (std::map<std::string,std::string>::const_iterator attrIt = _stringAttrib.begin();
301 attrIt != _stringAttrib.end(); ++attrIt) {
302 convSum->setStringAttribute((attrIt->first).c_str(), (attrIt->second).c_str()) ;
304 convSum->changeBasis(inBasis) ;
316 Int_t RooAddModel::basisCode(
const char* name)
const
318 TIterator* mIter = _pdfList.createIterator() ;
319 RooResolutionModel* model ;
320 Bool_t first(kTRUE), code(0) ;
321 while((model = (RooResolutionModel*)mIter->Next())) {
322 Int_t subCode = model->basisCode(name) ;
326 }
else if (subCode==0) {
344 RooAddModel::CacheElem* RooAddModel::getProjCache(
const RooArgSet* nset,
const RooArgSet* iset,
const char* rangeName)
const
347 CacheElem* cache = (CacheElem*) _projCacheMgr.getObj(nset,iset,0,RooNameReg::ptr(rangeName)) ;
353 cache =
new CacheElem ;
358 RooArgSet *fullDepList = getObservables(nset) ;
360 fullDepList->remove(*iset,kTRUE,kTRUE) ;
368 while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
369 coef=(RooAbsPdf*)_coefIter->Next() ;
372 RooArgSet supNSet(*fullDepList) ;
375 RooArgSet* pdfDeps = pdf->getObservables(nset) ;
377 supNSet.remove(*pdfDeps,kTRUE,kTRUE) ;
382 RooArgSet* coefDeps = coef ? coef->getObservables(nset) : 0 ;
384 supNSet.remove(*coefDeps,kTRUE,kTRUE) ;
389 TString name(GetName()) ;
391 name.Append(pdf->GetName()) ;
392 name.Append(
"_SupNorm") ;
393 if (supNSet.getSize()>0) {
394 snorm =
new RooRealIntegral(name,
"Supplemental normalization integral",RooRealConstant::value(1.0),supNSet) ;
396 snorm =
new RooRealVar(name,
"Unit Supplemental normalization integral",1.0) ;
398 cache->_suppNormList.addOwned(*snorm) ;
403 if (_verboseEval>1) {
404 cxcoutD(Caching) <<
"RooAddModel::syncSuppNormList(" << GetName() <<
") synching supplemental normalization list for norm" << (nset?*nset:RooArgSet()) << endl ;
405 if (dologD(Caching)) {
406 cache->_suppNormList.Print(
"v") ;
414 if (!_projectCoefs || _basis!=0 ) {
415 _projCacheMgr.setObj(nset,iset,cache,RooNameReg::ptr(rangeName)) ;
421 RooArgSet* nset2 = nset ? getObservables(nset) : new RooArgSet() ;
424 if (!nset2->equals(_refCoefNorm) || _refCoefRangeName !=0 || rangeName !=0 ) {
426 coutI(Caching) <<
"RooAddModel::syncCoefProjList(" << GetName() <<
") creating coefficient projection integrals" << endl ;
427 ccoutI(Caching) <<
" from current normalization: " ; nset2->Print(
"1") ;
428 ccoutI(Caching) <<
" with current range: " << (rangeName?rangeName:
"<none>") << endl ;
429 ccoutI(Caching) <<
" to reference normalization: " ; _refCoefNorm.Print(
"1") ;
430 ccoutI(Caching) <<
" with reference range: " << (_refCoefRangeName?RooNameReg::str(_refCoefRangeName):
"<none>") << endl ;
436 while((thePdf=(RooAbsPdf*)_pdfIter->Next())) {
439 RooAbsReal* pdfProj ;
440 if (!nset2->equals(_refCoefNorm)) {
441 pdfProj = thePdf->createIntegral(*nset2,_refCoefNorm) ;
442 pdfProj->setOperMode(operMode()) ;
444 TString name(GetName()) ;
446 name.Append(thePdf->GetName()) ;
447 name.Append(
"_ProjectNorm") ;
448 pdfProj =
new RooRealVar(name,
"Unit Projection normalization integral",1.0) ;
451 cache->_projList.addOwned(*pdfProj) ;
454 RooArgSet supNormSet(_refCoefNorm) ;
455 RooArgSet* deps = thePdf->getParameters(RooArgSet()) ;
456 supNormSet.remove(*deps,kTRUE,kTRUE) ;
460 TString name(GetName()) ;
462 name.Append(thePdf->GetName()) ;
463 name.Append(
"_ProjSupNorm") ;
464 if (supNormSet.getSize()>0) {
465 snorm =
new RooRealIntegral(name,
"Projection Supplemental normalization integral",
466 RooRealConstant::value(1.0),supNormSet) ;
468 snorm =
new RooRealVar(name,
"Unit Projection Supplemental normalization integral",1.0) ;
470 cache->_suppProjList.addOwned(*snorm) ;
473 RooAbsReal* rangeProj1 ;
474 if (_refCoefRangeName && _refCoefNorm.getSize()>0) {
475 rangeProj1 = thePdf->createIntegral(_refCoefNorm,_refCoefNorm,RooNameReg::str(_refCoefRangeName)) ;
476 rangeProj1->setOperMode(operMode()) ;
478 TString theName(GetName()) ;
479 theName.Append(
"_") ;
480 theName.Append(thePdf->GetName()) ;
481 theName.Append(
"_RangeNorm1") ;
482 rangeProj1 =
new RooRealVar(theName,
"Unit range normalization integral",1.0) ;
484 cache->_refRangeProjList.addOwned(*rangeProj1) ;
488 RooAbsReal* rangeProj2 ;
489 if (rangeName && _refCoefNorm.getSize()>0) {
490 rangeProj2 = thePdf->createIntegral(_refCoefNorm,_refCoefNorm,rangeName) ;
491 rangeProj2->setOperMode(operMode()) ;
493 TString theName(GetName()) ;
494 theName.Append(
"_") ;
495 theName.Append(thePdf->GetName()) ;
496 theName.Append(
"_RangeNorm2") ;
497 rangeProj2 =
new RooRealVar(theName,
"Unit range normalization integral",1.0) ;
499 cache->_rangeProjList.addOwned(*rangeProj2) ;
507 _projCacheMgr.setObj(nset,iset,cache,RooNameReg::ptr(rangeName)) ;
520 void RooAddModel::updateCoefficients(CacheElem& cache,
const RooArgSet* nset)
const
527 if (_allExtendable) {
530 Double_t coefSum(0) ;
531 for (i=0 ; i<_pdfList.getSize() ; i++) {
532 _coefCache[i] = ((RooAbsPdf*)_pdfList.at(i))->expectedEvents(_refCoefNorm.getSize()>0?&_refCoefNorm:nset) ;
533 coefSum += _coefCache[i] ;
536 coutW(Eval) <<
"RooAddModel::updateCoefCache(" << GetName() <<
") WARNING: total number of expected events is 0" << endl ;
538 for (i=0 ; i<_pdfList.getSize() ; i++) {
539 _coefCache[i] /= coefSum ;
547 Double_t coefSum(0) ;
548 for (i=0 ; i<_coefList.getSize() ; i++) {
549 _coefCache[i] = ((RooAbsPdf*)_coefList.at(i))->getVal(nset) ;
550 coefSum += _coefCache[i] ;
552 for (i=0 ; i<_coefList.getSize() ; i++) {
553 _coefCache[i] /= coefSum ;
558 Double_t lastCoef(1) ;
559 for (i=0 ; i<_coefList.getSize() ; i++) {
560 _coefCache[i] = ((RooAbsPdf*)_coefList.at(i))->getVal(nset) ;
561 cxcoutD(Caching) <<
"SYNC: orig coef[" << i <<
"] = " << _coefCache[i] << endl ;
562 lastCoef -= _coefCache[i] ;
564 _coefCache[_coefList.getSize()] = lastCoef ;
565 cxcoutD(Caching) <<
"SYNC: orig coef[" << _coefList.getSize() <<
"] = " << _coefCache[_coefList.getSize()] << endl ;
569 if ((lastCoef<-1e-05 || (lastCoef-1)>1e-5) && _coefErrCount-->0) {
570 coutW(Eval) <<
"RooAddModel::updateCoefCache(" << GetName()
571 <<
" WARNING: sum of PDF coefficients not in range [0-1], value="
572 << 1-lastCoef << endl ;
573 if (_coefErrCount==0) {
574 coutW(Eval) <<
" (no more will be printed)" << endl ;
583 if ((!_projectCoefs) || cache._projList.getSize()==0) {
589 Double_t coefSum(0) ;
590 for (i=0 ; i<_pdfList.getSize() ; i++) {
591 GlobalSelectComponentRAII compRAII(
true);
593 RooAbsReal* pp = ((RooAbsReal*)cache._projList.at(i)) ;
594 RooAbsReal* sn = ((RooAbsReal*)cache._suppProjList.at(i)) ;
595 RooAbsReal* r1 = ((RooAbsReal*)cache._refRangeProjList.at(i)) ;
596 RooAbsReal* r2 = ((RooAbsReal*)cache._rangeProjList.at(i)) ;
599 cxcoutD(Eval) <<
"pp = " << pp->GetName() << endl
600 <<
"sn = " << sn->GetName() << endl
601 <<
"r1 = " << r1->GetName() << endl
602 <<
"r2 = " << r2->GetName() << endl ;
603 r1->printStream(ccoutD(Eval),kName|kArgs|kValue,kSingleLine) ;
604 r1->printCompactTree(ccoutD(Eval)) ;
607 Double_t proj = pp->getVal()/sn->getVal()*(r2->getVal()/r1->getVal()) ;
609 _coefCache[i] *= proj ;
610 coefSum += _coefCache[i] ;
612 for (i=0 ; i<_pdfList.getSize() ; i++) {
613 _coefCache[i] /= coefSum ;
626 Double_t RooAddModel::evaluate()
const
628 const RooArgSet* nset = _normSet ;
629 CacheElem* cache = getProjCache(nset) ;
631 updateCoefficients(*cache,nset) ;
642 while((pdf = (RooAbsPdf*)_pdfIter->Next())) {
643 if (_coefCache[i]!=0.) {
644 snormVal = nset ? ((RooAbsReal*)cache->_suppNormList.at(i))->getVal() : 1.0 ;
645 Double_t pdfVal = pdf->getVal(nset) ;
647 if (pdf->isSelectedComp()) {
648 value += pdfVal*_coefCache[i]/snormVal ;
649 cxcoutD(Eval) <<
"RooAddModel::evaluate(" << GetName() <<
") value += ["
650 << pdf->GetName() <<
"] " << pdfVal <<
" * " << _coefCache[i] <<
" / " << snormVal << endl ;
665 void RooAddModel::resetErrorCounters(Int_t resetValue)
667 RooAbsPdf::resetErrorCounters(resetValue) ;
668 _coefErrCount = resetValue ;
678 Bool_t RooAddModel::checkObservables(
const RooArgSet* nset)
const
686 while((coef=(RooAbsReal*)_coefIter->Next())) {
687 pdf = (RooAbsReal*)_pdfIter->Next() ;
688 if (pdf->observableOverlaps(nset,*coef)) {
689 coutE(InputArguments) <<
"RooAddModel::checkObservables(" << GetName() <<
"): ERROR: coefficient " << coef->GetName()
690 <<
" and PDF " << pdf->GetName() <<
" have one or more dependents in common" << endl ;
702 Int_t RooAddModel::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
703 const RooArgSet* normSet,
const char* rangeName)
const
705 if (_forceNumInt)
return 0 ;
708 analVars.add(allVars) ;
713 getCompIntList(normSet,&allVars,cilist,code,rangeName) ;
724 void RooAddModel::getCompIntList(
const RooArgSet* nset,
const RooArgSet* iset, pRooArgList& compIntList, Int_t& code,
const char* isetRangeName)
const
726 Int_t sterileIdx(-1) ;
728 IntCacheElem* cache = (IntCacheElem*) _intCacheMgr.getObj(nset,iset,&sterileIdx,RooNameReg::ptr(isetRangeName)) ;
730 code = _intCacheMgr.lastIndex() ;
731 compIntList = &cache->_intList ;
737 cache =
new IntCacheElem ;
741 RooResolutionModel* model ;
742 while ((model=(RooResolutionModel*)_pdfIter->Next())) {
743 RooAbsReal* intPdf = model->createIntegral(*iset,nset,0,isetRangeName) ;
744 cache->_intList.addOwned(*intPdf) ;
748 code = _intCacheMgr.setObj(nset,iset,(RooAbsCacheElement*)cache,RooNameReg::ptr(isetRangeName)) ;
751 compIntList = &cache->_intList ;
759 Double_t RooAddModel::analyticalIntegralWN(Int_t code,
const RooArgSet* normSet,
const char* rangeName)
const
763 return getVal(normSet) ;
767 IntCacheElem* cache = (IntCacheElem*) _intCacheMgr.getObjByIndex(code-1) ;
769 RooArgList* compIntList ;
773 RooArgSet* vars = getParameters(RooArgSet()) ;
774 RooArgSet* nset = _intCacheMgr.nameSet1ByIndex(code-1)->select(*vars) ;
775 RooArgSet* iset = _intCacheMgr.nameSet2ByIndex(code-1)->select(*vars) ;
778 getCompIntList(nset,iset,compIntList,code2,rangeName) ;
785 compIntList = &cache->_intList ;
790 const RooArgSet* nset = _normSet ;
791 CacheElem* pcache = getProjCache(nset) ;
793 updateCoefficients(*pcache,nset) ;
796 TIterator* compIntIter = compIntList->createIterator() ;
803 while((pdfInt = (RooAbsReal*)compIntIter->Next())) {
804 if (_coefCache[i]!=0.) {
805 snormVal = nset ? ((RooAbsReal*)pcache->_suppNormList.at(i))->getVal() : 1.0 ;
806 Double_t intVal = pdfInt->getVal(nset) ;
807 value += intVal*_coefCache[i]/snormVal ;
808 cxcoutD(Eval) <<
"RooAddModel::evaluate(" << GetName() <<
") value += ["
809 << pdfInt->GetName() <<
"] " << intVal <<
" * " << _coefCache[i] <<
" / " << snormVal << endl ;
826 Double_t RooAddModel::expectedEvents(
const RooArgSet* nset)
const
828 Double_t expectedTotal(0.0);
831 if (_allExtendable) {
835 while((pdf = (RooAbsPdf*)_pdfIter->Next())) {
836 expectedTotal += pdf->expectedEvents(nset) ;
844 while((coef=(RooAbsReal*)_coefIter->Next())) {
845 expectedTotal += coef->getVal() ;
849 return expectedTotal;
858 void RooAddModel::selectNormalization(
const RooArgSet* depSet, Bool_t force)
860 if (!force && _refCoefNorm.getSize()!=0) {
865 fixCoefNormalization(RooArgSet()) ;
869 RooArgSet* myDepSet = getObservables(depSet) ;
870 fixCoefNormalization(*myDepSet) ;
880 void RooAddModel::selectNormalizationRange(
const char* rangeName, Bool_t force)
882 if (!force && _refCoefRangeName) {
886 fixCoefRange(rangeName) ;
894 RooAbsGenContext* RooAddModel::genContext(
const RooArgSet &vars,
const RooDataSet *prototype,
895 const RooArgSet* auxProto, Bool_t verbose)
const
897 return new RooAddGenContext(*
this,vars,prototype,auxProto,verbose) ;
905 Bool_t RooAddModel::isDirectGenSafe(
const RooAbsArg& arg)
const
909 while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
910 if (!pdf->isDirectGenSafe(arg)) {
922 Int_t RooAddModel::getGenerator(
const RooArgSet& directVars, RooArgSet &, Bool_t )
const
926 while((pdf=(RooAbsPdf*)_pdfIter->Next())) {
928 if (pdf->getGenerator(directVars,tmp)==0) {
941 void RooAddModel::generateEvent(Int_t )
952 RooArgList RooAddModel::CacheElem::containedArgs(Action)
955 allNodes.add(_projList) ;
956 allNodes.add(_suppProjList) ;
957 allNodes.add(_refRangeProjList) ;
958 allNodes.add(_rangeProjList) ;
968 RooArgList RooAddModel::IntCacheElem::containedArgs(Action)
970 RooArgList allNodes(_intList) ;
979 void RooAddModel::printMetaArgs(ostream& os)
const
984 Bool_t first(kTRUE) ;
987 RooAbsArg* coef, *pdf ;
988 while((coef=(RooAbsArg*)_coefIter->Next())) {
994 pdf=(RooAbsArg*)_pdfIter->Next() ;
995 os << coef->GetName() <<
" * " << pdf->GetName() ;
997 pdf = (RooAbsArg*) _pdfIter->Next() ;
999 os <<
" + [%] * " << pdf->GetName() ;