179 ClassImp(RooCustomizer);
185 static Int_t dummy = init() ;
189 RooFactoryWSTool::IFace* iface =
new RooCustomizer::CustIFace ;
190 RooFactoryWSTool::registerSpecial(
"EDIT",iface) ;
218 RooCustomizer::RooCustomizer(
const RooAbsArg& pdf,
const RooAbsCategoryLValue& masterCat,
219 RooArgSet& splitLeafs, RooArgSet* splitLeafsAll) :
220 TNamed(pdf.GetName(),pdf.GetTitle()),
223 _masterPdf((RooAbsArg*)&pdf),
224 _masterCat((RooAbsCategoryLValue*)&masterCat),
225 _masterBranchList(
"masterBranchList"),
226 _masterLeafList(
"masterLeafList"),
227 _internalCloneBranchList(
"cloneBranchList"),
228 _cloneNodeListAll(splitLeafsAll),
229 _cloneNodeListOwned(&splitLeafs)
231 _cloneBranchList = &_internalCloneBranchList ;
243 RooCustomizer::RooCustomizer(
const RooAbsArg& pdf,
const char* name) :
244 TNamed(pdf.GetName(),pdf.GetTitle()),
248 _masterPdf((RooAbsArg*)&pdf),
250 _masterBranchList(
"masterBranchList"),
251 _masterLeafList(
"masterLeafList"),
252 _internalCloneBranchList(
"cloneBranchList"),
253 _cloneNodeListAll(0),
254 _cloneNodeListOwned(0)
256 _cloneBranchList = &_internalCloneBranchList ;
267 void RooCustomizer::initialize()
269 _masterPdf->leafNodeServerList(&_masterLeafList) ;
270 _masterPdf->branchNodeServerList(&_masterBranchList) ;
278 RooCustomizer::~RooCustomizer()
294 void RooCustomizer::splitArgs(
const RooArgSet& set,
const RooAbsCategory& splitCat)
297 coutE(InputArguments) <<
"RooCustomizer::splitArgs(" << _name
298 <<
") ERROR cannot set spitting rules on this sterile customizer" << endl ;
302 for (
auto arg : set) {
303 splitArg(*arg,splitCat) ;
317 void RooCustomizer::splitArg(
const RooAbsArg& arg,
const RooAbsCategory& splitCat)
319 if (_splitArgList.FindObject(arg.GetName())) {
320 coutE(InputArguments) <<
"RooCustomizer(" << GetName() <<
") ERROR: multiple splitting rules defined for "
321 << arg.GetName() <<
" only using first rule" << endl ;
326 coutE(InputArguments) <<
"RooCustomizer::splitArg(" << _name
327 <<
") ERROR cannot set spitting rules on this sterile customizer" << endl ;
331 _splitArgList.Add((RooAbsArg*)&arg) ;
332 _splitCatList.Add((RooAbsCategory*)&splitCat) ;
340 void RooCustomizer::replaceArg(
const RooAbsArg& orig,
const RooAbsArg& subst)
342 if (_replaceArgList.FindObject(orig.GetName())) {
343 coutE(InputArguments) <<
"RooCustomizer(" << GetName() <<
") ERROR: multiple replacement rules defined for "
344 << orig.GetName() <<
" only using first rule" << endl ;
348 _replaceArgList.Add((RooAbsArg*)&orig) ;
349 _replaceSubList.Add((RooAbsArg*)&subst) ;
360 RooAbsArg* RooCustomizer::build(Bool_t verbose)
363 RooAbsArg* ret = doBuild(_name.Length()>0?_name.Data():0,verbose) ;
369 if (_cloneNodeListOwned) {
370 allOwned.add(*_cloneNodeListOwned) ;
372 allOwned.add(*_cloneBranchList) ;
375 allOwned.remove(*ret) ;
379 if (allOwned.getSize()>0) {
380 ret->addOwnedComponents(allOwned) ;
396 RooAbsArg* RooCustomizer::build(
const char* masterCatState, Bool_t verbose)
399 coutE(InputArguments) <<
"RooCustomizer::build(" << _name
400 <<
") ERROR cannot use leaf spitting build() on this sterile customizer" << endl ;
405 if (_masterCat->setLabel(masterCatState)) {
406 coutE(InputArguments) <<
"RooCustomizer::build(" << _masterPdf->GetName() <<
"): ERROR label '" << masterCatState
407 <<
"' not defined for master splitting category " << _masterCat->GetName() << endl ;
411 return doBuild(masterCatState,verbose) ;
419 RooAbsArg* RooCustomizer::doBuild(
const char* masterCatState, Bool_t verbose)
422 RooArgSet masterNodesToBeSplit(
"masterNodesToBeSplit") ;
423 RooArgSet masterNodesToBeReplaced(
"masterNodesToBeReplaced") ;
424 RooArgSet masterReplacementNodes(
"masterReplacementNodes") ;
425 RooArgSet clonedMasterNodes(
"clonedMasterNodes") ;
428 RooArgSet nodeList(_masterLeafList) ;
429 nodeList.add(_masterBranchList) ;
432 for (
auto node : nodeList) {
433 RooAbsArg* theSplitArg = !_sterile?(RooAbsArg*) _splitArgList.FindObject(node->GetName()):0 ;
435 RooAbsCategory* splitCat = (RooAbsCategory*) _splitCatList.At(_splitArgList.IndexOf(theSplitArg)) ;
437 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName()
438 <<
"): tree node " << node->GetName() <<
" is split by category " << splitCat->GetName() << endl ;
441 TString newName(node->GetName()) ;
442 if (masterCatState) {
443 newName.Append(
"_") ;
444 newName.Append(splitCat->getLabel()) ;
448 RooAbsArg* specNode = _cloneNodeListAll ? _cloneNodeListAll->find(newName) : _cloneNodeListOwned->find(newName) ;
452 clonedMasterNodes.add(*specNode) ;
454 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName()
455 <<
") Adding existing node specialization " << newName <<
" to clonedMasterNodes" << endl ;
459 TString nameAttrib(
"ORIGNAME:") ;
460 nameAttrib.Append(node->GetName()) ;
461 specNode->setAttribute(nameAttrib) ;
463 if (!specNode->getStringAttribute(
"origName")) {
464 specNode->setStringAttribute(
"origName",node->GetName()) ;
471 if (node->isDerived()) {
472 coutW(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName()
473 <<
"): WARNING: branch node " << node->GetName() <<
" is split but has no pre-defined specializations" << endl ;
476 TString newTitle(node->GetTitle()) ;
477 newTitle.Append(
" (") ;
478 newTitle.Append(splitCat->getLabel()) ;
479 newTitle.Append(
")") ;
482 RooAbsArg* clone = (RooAbsArg*) node->Clone(newName.Data()) ;
483 clone->setStringAttribute(
"factory_tag",0) ;
484 clone->SetTitle(newTitle) ;
487 TString nameAttrib(
"ORIGNAME:") ;
488 nameAttrib.Append(node->GetName()) ;
489 clone->setAttribute(nameAttrib) ;
491 if (!clone->getStringAttribute(
"origName")) {
492 clone->setStringAttribute(
"origName",node->GetName()) ;
496 clonedMasterNodes.add(*clone) ;
498 _cloneNodeListOwned->addOwned(*clone) ;
500 _cloneNodeListOwned->add(*clone) ;
502 if (_cloneNodeListAll) {
503 _cloneNodeListAll->add(*clone) ;
506 masterNodesToBeSplit.add(*node) ;
509 RooAbsArg* ReplaceArg = (RooAbsArg*) _replaceArgList.FindObject(node->GetName()) ;
511 RooAbsArg* substArg = (RooAbsArg*) _replaceSubList.At(_replaceArgList.IndexOf(ReplaceArg)) ;
513 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName()
514 <<
"): tree node " << node->GetName() <<
" will be replaced by " << substArg->GetName() << endl ;
518 TString nameAttrib(
"ORIGNAME:") ;
519 nameAttrib.Append(node->GetName()) ;
520 substArg->setAttribute(nameAttrib) ;
523 masterNodesToBeReplaced.add(*node) ;
524 masterReplacementNodes.add(*substArg) ;
529 RooArgSet masterBranchesToBeCloned(
"masterBranchesToBeCloned") ;
530 for (
auto branch : _masterBranchList) {
533 if (masterNodesToBeSplit.find(branch->GetName())) {
535 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName() <<
") Branch node " << branch->GetName() <<
" is already split" << endl ;
539 if (masterNodesToBeReplaced.find(branch->GetName())) {
541 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName() <<
") Branch node " << branch->GetName() <<
" is already replaced" << endl ;
546 if (branch->dependsOn(masterNodesToBeSplit)) {
548 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName() <<
") Branch node "
549 << branch->IsA()->GetName() <<
"::" << branch->GetName() <<
" cloned: depends on a split parameter" << endl ;
551 masterBranchesToBeCloned.add(*branch) ;
552 }
else if (branch->dependsOn(masterNodesToBeReplaced)) {
554 coutI(ObjectHandling) <<
"RooCustomizer::build(" << _masterPdf->GetName() <<
") Branch node "
555 << branch->IsA()->GetName() <<
"::" << branch->GetName() <<
" cloned: depends on a replaced parameter" << endl ;
557 masterBranchesToBeCloned.add(*branch) ;
562 RooAbsArg* cloneTopPdf = 0;
563 RooArgSet clonedMasterBranches(
"clonedMasterBranches") ;
565 for (
auto branch : masterBranchesToBeCloned) {
566 TString newName(branch->GetName()) ;
567 if (masterCatState) {
568 newName.Append(
"_") ;
569 newName.Append(masterCatState) ;
573 RooAbsArg* clone = (RooAbsArg*) branch->Clone(newName.Data()) ;
574 clone->setStringAttribute(
"factory_tag",0) ;
575 TString nameAttrib(
"ORIGNAME:") ;
576 nameAttrib.Append(branch->GetName()) ;
577 clone->setAttribute(nameAttrib) ;
579 if (!clone->getStringAttribute(
"origName")) {
580 clone->setStringAttribute(
"origName",branch->GetName()) ;
583 clonedMasterBranches.add(*clone) ;
586 if (branch==_masterPdf) cloneTopPdf=(RooAbsArg*)clone ;
590 _cloneBranchList->addOwned(clonedMasterBranches) ;
592 _cloneBranchList->add(clonedMasterBranches) ;
596 for (
auto branch : clonedMasterBranches) {
597 branch->redirectServers(clonedMasterBranches,kFALSE,kTRUE) ;
598 branch->redirectServers(clonedMasterNodes,kFALSE,kTRUE) ;
599 branch->redirectServers(masterReplacementNodes,kFALSE,kTRUE) ;
602 return cloneTopPdf ? cloneTopPdf : _masterPdf ;
609 void RooCustomizer::printName(ostream& os)
const
618 void RooCustomizer::printTitle(ostream& os)
const
627 void RooCustomizer::printClassName(ostream& os)
const
629 os << IsA()->GetName() ;
636 void RooCustomizer::printArgs(ostream& os)
const
638 os <<
"[ masterPdf=" << _masterPdf->GetName() ;
640 os <<
" masterCat=" << _masterCat->GetName() ;
650 void RooCustomizer::printMultiline(ostream& os, Int_t , Bool_t , TString indent)
const
652 os << indent <<
"RooCustomizer for " << _masterPdf->GetName() << (_sterile?
" (sterile)":
"") << endl ;
654 Int_t i, nsplit = _splitArgList.GetSize() ;
656 os << indent <<
" Splitting rules:" << endl ;
657 for (i=0 ; i<nsplit ; i++) {
658 os << indent <<
" " << _splitArgList.At(i)->GetName() <<
" is split by " << _splitCatList.At(i)->GetName() << endl ;
662 Int_t nrepl = _replaceArgList.GetSize() ;
664 os << indent <<
" Replacement rules:" << endl ;
665 for (i=0 ; i<nrepl ; i++) {
666 os << indent <<
" " << _replaceSubList.At(i)->GetName() <<
" replaces " << _replaceArgList.At(i)->GetName() << endl ;
679 void RooCustomizer::setCloneBranchSet(RooArgSet& cloneBranchSet)
681 _cloneBranchList = &cloneBranchSet ;
682 _cloneBranchList->setHashTableSize(1000) ;
690 std::string RooCustomizer::CustIFace::create(RooFactoryWSTool& ft,
const char* typeName,
const char* instanceName, std::vector<std::string> args)
694 throw string(Form(
"RooCustomizer::CustIFace::create() ERROR: expect at least 2 arguments for EDIT: the input object and at least one $Replace() rule")) ;
697 if (
string(typeName)!=
"EDIT") {
698 throw string(Form(
"RooCustomizer::CustIFace::create() ERROR: unknown type requested: %s",typeName)) ;
702 RooAbsArg* arg = ft.ws().arg(args[0].c_str()) ;
704 throw string(Form(
"RooCustomizer::CustIFace::create() ERROR: input RooAbsArg %s does not exist",args[0].c_str())) ;
708 if (args[0]==instanceName) {
713 RooCustomizer cust(*arg,instanceName) ;
715 for (
unsigned int i=1 ; i<args.size() ; i++) {
717 strlcpy(buf,args[i].c_str(),1024) ;
718 char* sep = strchr(buf,
'=') ;
720 throw string(Form(
"RooCustomizer::CustIFace::create() ERROR: unknown argument: %s, expect form orig=subst",args[i].c_str())) ;
723 RooAbsArg* orig = ft.ws().arg(buf) ;
724 RooAbsArg* subst(0) ;
725 if (
string(sep+1).find(
"$REMOVE")==0) {
728 subst = &RooRealConstant::removalDummy() ;
731 char* sep2 = strchr(sep+1,
'(') ;
734 strlcpy(buf2,sep2+1,1024) ;
736 char* tok = R__STRTOK_R(buf2,
",)",&saveptr) ;
739 subst->setAttribute(Form(
"REMOVE_FROM_%s",tok)) ;
740 tok = R__STRTOK_R(0,
",)",&saveptr) ;
744 subst->setAttribute(
"REMOVE_ALL") ;
748 subst = ft.ws().arg(sep+1) ;
757 cust.replaceArg(*orig,*subst) ;
759 oocoutW((TObject*)0,ObjectHandling) <<
"RooCustomizer::CustIFace::create() WARNING: input or replacement of a replacement operation not found, operation ignored"<< endl ;
764 RooAbsArg* targ = cust.build(kFALSE) ;
766 throw string(Form(
"RooCustomizer::CustIFace::create() ERROR in customizer build, object %snot created",instanceName)) ;
772 targ->SetName(instanceName) ;
773 ft.ws().import(cust.cloneBranchList(),RooFit::Silence(),RooFit::NoRecursion(kTRUE)) ;
775 ft.ws().import(cust.cloneBranchList(),RooFit::Silence(),RooFit::RenameConflictNodes(
"orig",1),RooFit::NoRecursion(kTRUE)) ;
778 return string(instanceName?instanceName:targ->GetName()) ;