454 using namespace std ;
456 ClassImp(RooSimPdfBuilder);
463 RooSimPdfBuilder::RooSimPdfBuilder(
const RooArgSet& protoPdfSet) :
464 _protoPdfSet(protoPdfSet)
466 _compSplitCatSet.setHashTableSize(1000) ;
467 _splitNodeList.setHashTableSize(10000) ;
468 _splitNodeListOwned.setHashTableSize(10000) ;
477 RooArgSet* RooSimPdfBuilder::createProtoBuildConfig()
479 RooArgSet* buildConfig =
new RooArgSet ;
480 buildConfig->addOwned(*
new RooStringVar(
"physModels",
"List and mapping of physics models to include in build",
"",4096)) ;
481 buildConfig->addOwned(*
new RooStringVar(
"splitCats",
"List of categories used for splitting",
"",1024)) ;
483 TIterator* iter = _protoPdfSet.createIterator() ;
485 while ((proto=(RooAbsPdf*)iter->Next())) {
486 buildConfig->addOwned(*
new RooStringVar(proto->GetName(),proto->GetName(),
"",4096)) ;
497 void RooSimPdfBuilder::addSpecializations(
const RooArgSet& specSet)
499 _splitNodeList.add(specSet) ;
507 RooSimultaneous* RooSimPdfBuilder::buildPdf(
const RooArgSet& buildConfig,
const RooArgSet& dependents,
508 const RooArgSet* auxSplitCats, Bool_t verbose)
510 const char* spaceChars =
" \t" ;
513 Int_t buflen = strlen(((RooStringVar*)buildConfig.find(
"physModels"))->getVal())+1 ;
514 char *buf =
new char[buflen] ;
516 strlcpy(buf,((RooStringVar*)buildConfig.find(
"physModels"))->getVal(),buflen) ;
517 RooAbsCategoryLValue* physCat(0) ;
518 if (strstr(buf,
" : ")) {
519 const char* physCatName = strtok(buf,spaceChars) ;
520 physCat =
dynamic_cast<RooAbsCategoryLValue*
>(dependents.find(physCatName)) ;
522 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR physics index category " << physCatName
523 <<
" not found in dataset variables" << endl ;
527 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: category indexing physics model: " << physCatName << endl ;
532 RooArgSet physModelSet ;
535 strtok(0,spaceChars) ;
536 physName = strtok(0,spaceChars) ;
538 physName = strtok(buf,spaceChars) ;
542 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR: No models specified, nothing to do!" << endl ;
547 Bool_t first(kTRUE) ;
554 if (strchr(physName,
'=')) {
557 coutW(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: WARNING: without physCat specification "
558 <<
"<physCatState>=<pdfProtoName> association is meaningless" << endl ;
560 stateName = physName ;
561 physName = strchr(stateName,
'=') ;
566 stateName = physName ;
569 RooAbsPdf* physModel = (RooAbsPdf*) (physName ? _protoPdfSet.find(physName) : 0 );
571 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR requested physics model "
572 << (physName?physName:
"(null)") <<
" is not defined" << endl ;
578 if (stateMap.find(stateName)) {
579 coutW(InputArguments) <<
"RooSimPdfBuilder::buildPdf: WARNING: multiple PDFs specified for state "
580 << stateName <<
", only first will be used" << endl ;
585 physModelSet.add(*physModel,kTRUE) ;
588 stateMap.addOwned(*
new RooStringVar(stateName,stateName,physName)) ;
591 physName = strtok(0,spaceChars) ;
594 }
else if (physCat==0) {
595 coutW(InputArguments) <<
"RooSimPdfBuilder::buildPdf: WARNING: without physCat specification, only the first model will be used" << endl ;
599 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: list of physics models " << physModelSet << endl ;
604 TList splitStateList ;
605 RooArgSet splitCatSet ;
608 buflen = strlen(((RooStringVar*)buildConfig.find(
"splitCats"))->getVal())+1 ;
609 buf =
new char[buflen] ;
610 strlcpy(buf,((RooStringVar*)buildConfig.find(
"splitCats"))->getVal(),buflen) ;
612 char *catName = strtok(buf,spaceChars) ;
618 if (strchr(catName,
'(')) {
620 catName = R__STRTOK_R(catName,
"(",&tokenPtr) ;
621 stateList = R__STRTOK_R(0,
")",&tokenPtr) ;
627 RooCategory* splitCat = catName ?
dynamic_cast<RooCategory*
>(dependents.find(catName)) : 0 ;
629 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR requested split category " << (catName?catName:
"(null)")
630 <<
" is not a RooCategory in the dataset" << endl ;
634 splitCatSet.add(*splitCat) ;
638 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: splitting of category " << catName
639 <<
" restricted to states (" << stateList <<
")" << endl ;
642 TList* slist =
new TList ;
643 slist->SetName(catName) ;
644 splitStateList.Add(slist) ;
646 char* stateLabel = R__STRTOK_R(stateList,
",",&tokenPtr) ;
650 const RooCatType* type = splitCat->lookupType(stateLabel) ;
652 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR splitCat " << splitCat->GetName()
653 <<
" doesn't have a state named " << stateLabel << endl ;
654 splitStateList.Delete() ;
658 slist->Add((TObject*)type) ;
660 stateLabel = R__STRTOK_R(0,
",",&tokenPtr) ;
664 catName = strtok(0,spaceChars) ;
666 if (physCat) splitCatSet.add(*physCat) ;
667 RooSuperCategory masterSplitCat(
"masterSplitCat",
"Master splitting category",splitCatSet) ;
669 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: list of splitting categories " << splitCatSet << endl ;
672 RooArgSet auxSplitSet ;
673 RooArgSet* auxSplitCloneSet(0) ;
676 auxSplitCloneSet = (RooArgSet*) auxSplitCats->snapshot(kTRUE) ;
677 if (!auxSplitCloneSet) {
678 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf(" << GetName() <<
") Couldn't deep-clone set auxiliary splitcats, abort." << endl ;
683 TIterator* iter = auxSplitCats->createIterator() ;
685 while((arg=(RooAbsArg*)iter->Next())) {
687 RooAbsArg* aux = auxSplitCats->find(arg->GetName()) ;
690 if (splitCatSet.find(aux->GetName())) {
691 coutW(InputArguments) <<
"RooSimPdfBuilder::buildPdf: WARNING: dataset contains a fundamental splitting category " << endl
692 <<
" with the same name as an auxiliary split function (" << aux->GetName() <<
"). " << endl
693 <<
" Auxiliary split function will be ignored" << endl ;
698 RooArgSet* parSet = aux->getParameters(splitCatSet) ;
699 if (parSet->getSize()>0) {
700 coutW(InputArguments) <<
"RooSimPdfBuilder::buildPdf: WARNING: ignoring auxiliary category " << aux->GetName()
701 <<
" because it has servers that are not listed in splitCatSet: " << *parSet << endl ;
707 aux->recursiveRedirectServers(splitCatSet) ;
710 auxSplitSet.add(*aux) ;
714 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: list of auxiliary splitting categories " << auxSplitSet << endl ;
718 TList* customizerList =
new TList ;
721 TIterator* physIter = physModelSet.createIterator() ;
722 RooAbsPdf* physModel ;
723 while((physModel=(RooAbsPdf*)physIter->Next())) {
724 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: processing physics model " << physModel->GetName() << endl ;
726 RooCustomizer* physCustomizer =
new RooCustomizer(*physModel,masterSplitCat,_splitNodeList) ;
727 customizerList->Add(physCustomizer) ;
730 RooStringVar* ruleStr = (RooStringVar*) buildConfig.find(physModel->GetName()) ;
734 buflen = strlen(ruleStr->getVal())+1 ;
735 buf =
new char[buflen] ;
737 strlcpy(buf,ruleStr->getVal(),buflen) ;
740 char* token = R__STRTOK_R(buf,spaceChars,&tokenPtr) ;
742 enum Mode { SplitCat, Colon, ParamList } ;
743 Mode mode(SplitCat) ;
746 RooAbsCategory* splitCat(0) ;
753 splitCatName = token ;
755 if (strchr(splitCatName,
',')) {
759 splitCat = (RooAbsCategory*) _compSplitCatSet.find(splitCatName) ;
760 TString origCompCatName(splitCatName) ;
765 char *catName2 = R__STRTOK_R(token,
",",&tokptr) ;
767 RooArgSet compCatSet ;
769 RooAbsArg* cat = splitCatSet.find(catName2) ;
773 cat = (RooAbsCategory*) auxSplitSet.find(catName2) ;
777 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR " << catName2
778 <<
" not found in the primary or auxilary splitcat list" << endl ;
779 customizerList->Delete() ;
780 delete customizerList ;
782 splitStateList.Delete() ;
786 compCatSet.add(*cat) ;
788 catName2 = R__STRTOK_R(0,
",",&tokptr) ;
794 TIterator* iter = compCatSet.createIterator() ;
796 while((arg=(RooAbsArg*)iter->Next())) {
797 RooArgSet tmp(compCatSet) ;
799 if (arg->dependsOnValue(tmp)) {
800 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPDF: ERROR: Ill defined split: auxiliary splitting category " << arg->GetName()
801 <<
" used in composite split " << compCatSet <<
" depends on one or more of the other splitting categories in the composite split" << endl ;
804 customizerList->Delete() ;
805 delete customizerList ;
806 splitStateList.Delete() ;
813 splitCat =
new RooMultiCategory(origCompCatName,origCompCatName,compCatSet) ;
814 _compSplitCatSet.addOwned(*splitCat) ;
821 splitCat = (RooAbsCategory*) splitCatSet.find(splitCatName) ;
825 splitCat = (RooAbsCategory*) auxSplitSet.find(splitCatName) ;
829 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR splitting category "
830 << splitCatName <<
" not found in the primary or auxiliary splitcat list" << endl ;
831 customizerList->Delete() ;
832 delete customizerList ;
833 splitStateList.Delete() ;
844 if (strcmp(token,
":")) {
845 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR in parsing, expected ':' after "
846 << splitCat <<
", found " << token << endl ;
847 customizerList->Delete() ;
848 delete customizerList ;
849 splitStateList.Delete() ;
859 RooArgSet splitParamList ;
860 RooArgSet* paramList = physModel->getParameters(dependents) ;
863 RooArgSet* compList = physModel->getComponents() ;
864 paramList->add(*compList) ;
867 Bool_t lastCharIsComma = (token[strlen(token)-1]==
',') ;
870 char *paramName = R__STRTOK_R(token,
",",&tokptr) ;
873 char *remainderState = 0 ;
875 if (paramName && R__STRTOK_R(paramName,
"[",&tokptr2)) {
876 remainderState = R__STRTOK_R(0,
"]",&tokptr2) ;
882 if (remainderState) {
883 if (!splitCat->lookupType(remainderState)) {
884 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR fraction split of parameter "
885 << paramName <<
" has invalid remainder state name: " << remainderState << endl ;
887 customizerList->Delete() ;
888 delete customizerList ;
889 splitStateList.Delete() ;
895 RooAbsArg* param = paramList->find(paramName) ;
897 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR " << paramName
898 <<
" is not a parameter of physics model " << physModel->GetName() << endl ;
900 customizerList->Delete() ;
901 delete customizerList ;
902 splitStateList.Delete() ;
906 splitParamList.add(*param) ;
909 if (remainderState) {
912 if (!dynamic_cast<RooAbsReal*>(param)) {
913 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR fraction split requested of non-real valued parameter "
914 << param->GetName() << endl ;
916 customizerList->Delete() ;
917 delete customizerList ;
918 splitStateList.Delete() ;
924 TList* remStateSplitList =
static_cast<TList*
>(splitStateList.FindObject(splitCat->GetName())) ;
927 if (remStateSplitList && !remStateSplitList->FindObject(remainderState)) {
928 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR " << paramName
929 <<
" remainder state " << remainderState <<
" in parameter split "
930 << param->GetName() <<
" is not actually being built" << endl ;
932 customizerList->Delete() ;
933 delete customizerList ;
934 splitStateList.Delete() ;
939 TIterator* iter = splitCat->typeIterator() ;
941 RooArgList fracLeafList ;
942 TString formExpr(
"1") ;
945 while((type=(RooCatType*)iter->Next())) {
948 if (!TString(type->GetName()).CompareTo(remainderState))
continue ;
951 if (remStateSplitList && !remStateSplitList->FindObject(type->GetName())) {
956 TString splitLeafName(param->GetName()) ;
957 splitLeafName.Append(
"_") ;
958 splitLeafName.Append(type->GetName()) ;
961 RooAbsArg* splitLeaf = _splitNodeList.find(splitLeafName) ;
964 splitLeaf = (RooAbsArg*) param->clone(splitLeafName) ;
965 _splitNodeList.add(*splitLeaf) ;
966 _splitNodeListOwned.addOwned(*splitLeaf) ;
968 fracLeafList.add(*splitLeaf) ;
969 formExpr.Append(Form(
"-@%d",i++)) ;
974 TString remLeafName(param->GetName()) ;
975 remLeafName.Append(
"_") ;
976 remLeafName.Append(remainderState) ;
979 if (!_splitNodeList.find(remLeafName)) {
980 RooAbsArg* remLeaf =
new RooFormulaVar(remLeafName,formExpr,fracLeafList) ;
981 _splitNodeList.add(*remLeaf) ;
982 _splitNodeListOwned.addOwned(*remLeaf) ;
983 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: creating remainder fraction formula for " << remainderState
984 <<
" specialization of split parameter " << param->GetName() <<
" " << formExpr << endl ;
989 paramName = R__STRTOK_R(0,
",",&tokptr) ;
990 if (paramName && R__STRTOK_R(paramName,
"[",&tokptr2)) {
991 remainderState = R__STRTOK_R(0,
"]",&tokptr2) ;
996 physCustomizer->splitArgs(splitParamList,*splitCat) ;
1000 if (!lastCharIsComma) mode = SplitCat ;
1005 token = R__STRTOK_R(0,spaceChars,&tokenPtr) ;
1008 if (mode!=SplitCat) {
1009 coutE(InputArguments) <<
"RooSimPdfBuilder::buildPdf: ERROR in parsing, expected "
1010 << (mode==Colon?
":":
"parameter list") <<
" after " << (token?token:
"(null)") << endl ;
1015 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: no splitting rules for " << physModel->GetName() << endl ;
1019 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: configured customizers for all physics models" << endl ;
1020 if (oodologI((TObject*)0,ObjectHandling)) {
1021 customizerList->Print() ;
1025 RooArgSet fitCatList ;
1026 if (physCat) fitCatList.add(*physCat) ;
1027 fitCatList.add(splitCatSet) ;
1028 TIterator* fclIter = fitCatList.createIterator() ;
1029 RooSuperCategory *fitCat =
new RooSuperCategory(
"fitCat",
"fitCat",fitCatList) ;
1032 RooSimultaneous* simPdf =
new RooSimultaneous(
"simPdf",
"simPdf",*fitCat) ;
1035 TIterator* fcIter = fitCat->typeIterator() ;
1037 RooCatType* fcState ;
1038 while((fcState=(RooCatType*)fcIter->Next())) {
1040 fitCat->setLabel(fcState->GetName()) ;
1044 RooAbsCategory* splitCat ;
1045 Bool_t select(kTRUE) ;
1046 while((splitCat=(RooAbsCategory*)fclIter->Next())) {
1048 TList* slist = (TList*) splitStateList.FindObject(splitCat->GetName()) ;
1049 if (!slist) continue ;
1050 RooCatType* type = (RooCatType*) slist->FindObject(splitCat->getLabel()) ;
1055 if (!select) continue ;
1059 RooCustomizer* physCustomizer ;
1061 RooStringVar* physNameVar = (RooStringVar*) stateMap.find(physCat->getLabel()) ;
1062 if (!physNameVar) continue ;
1063 physCustomizer = (RooCustomizer*) customizerList->FindObject(physNameVar->getVal());
1065 physCustomizer = (RooCustomizer*) customizerList->First() ;
1068 coutI(ObjectHandling) <<
"RooSimPdfBuilder::buildPdf: Customizing physics model " << physCustomizer->GetName()
1069 <<
" for mode " << fcState->GetName() << endl ;
1072 RooAbsPdf* fcPdf = (RooAbsPdf*) physCustomizer->build(masterSplitCat.getLabel(),verbose) ;
1073 simPdf->addPdf(*fcPdf,fcState->GetName()) ;
1078 _retiredCustomizerList.AddAll(customizerList) ;
1079 delete customizerList ;
1082 splitStateList.Delete() ;
1084 if (auxSplitCloneSet)
delete auxSplitCloneSet ;
1088 _simPdfList.push_back(simPdf) ;
1089 _fitCatList.push_back(fitCat) ;
1099 RooSimPdfBuilder::~RooSimPdfBuilder()
1101 _retiredCustomizerList.Delete() ;
1103 std::list<RooSimultaneous*>::iterator iter = _simPdfList.begin() ;
1104 while(iter != _simPdfList.end()) {
1109 std::list<RooSuperCategory*>::iterator iter2 = _fitCatList.begin() ;
1110 while(iter2 != _fitCatList.end()) {