RooCustomizer.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooCustomizer.cxx 36230 2010-10-09 20:21:02Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 // 
00019 // RooCustomizer is a factory class to produce clones
00020 // of a prototype composite PDF object with the same structure but
00021 // different leaf servers (parameters or dependents)
00022 //
00023 // RooCustomizer supports two kinds of modifications:
00024 // 
00025 // -> replace(leaf_arg,repl_arg) 
00026 // replaces each occurence of leaf_arg with repl_arg in the composite pdf.
00027 //
00028 // -> split(split_arg)
00029 // is used when building multiple clones of the same prototype. Each
00030 // occurrence of split_arg is replaceed with a clone of split_arg
00031 // named split_arg_[MCstate], where [MCstate] is the name of the
00032 // 'master category state' that indexes the clones to be built.
00033 //
00034 //
00035 // [Example]
00036 //
00037 // Splitting is particularly useful when building simultaneous fits to
00038 // subsets of the data sample with different background properties.
00039 // In such a case, the user builds a single prototype PDF representing
00040 // the structure of the signal and background and splits the dataset
00041 // into categories with different background properties. Using
00042 // RooCustomizer a PDF for each subfit can be constructed from the
00043 // prototype that has same structure and signal parameters, but
00044 // different instances of the background parameters: e.g.
00045 //
00046 //     ...
00047 //     RooExponential bg("bg","background",x,alpha) ;
00048 //     RooGaussian sig("sig","signal",x,mean,sigma) ;
00049 //     RooAddPdf pdf("pdf","pdf",sig,bg,sigfrac) ;
00050 //
00051 //     RooDataSet data("data","dataset",RooArgSet(x,runblock),...)
00052 //
00053 //     RooCategory runblock("runblock","run block") ;
00054 //     runblock.defineType("run1") ;
00055 //     runblock.defineType("run2") ;
00056 //
00057 //     RooArgSet splitLeafs
00058 //     RooCustomizer cust(pdf,runblock,splitLeafs)
00059 //     cust.split(alpha,runblock)
00060 //
00061 //     RooAbsPdf* pdf_run1 = cust.build("run1") ;
00062 //     RooAbsPdf* pdf_run2 = cust.build("run2") ;
00063 //
00064 //     RooSimultaneous simpdf("simpdf","simpdf",RooArgSet(*pdf_run1,*pdf_run2)) 
00065 //
00066 // If the master category state is a super category, leafs may be split
00067 // by any subset of that master category. E.g. if the master category
00068 // is 'A x B', leafs may be split by A, B or AxB.
00069 //
00070 // In addition to replacing leaf nodes, RooCustomizer clones all branch
00071 // nodes that depend directly or indirectly on modified leaf nodes, so
00072 // that the input pdf is untouched by each build operation.
00073 //
00074 // The customizer owns all the branch nodes including the returned top
00075 // level node, so the customizer should live as longs as the cloned
00076 // composites are needed.
00077 //
00078 // Any leaf nodes that are created by the customizer will be put into
00079 // the leaf list that is passed into the customizers constructor (splitLeafs in
00080 // the above example. The list owner is responsible for deleting these leaf
00081 // nodes after the customizer is deleted.
00082 //
00083 //
00084 // [Advanced techniques]
00085 //
00086 // By default the customizer clones the prototype leaf node when splitting a leaf,
00087 // but the user can feed pre-defined split leafs in leaf list. These leafs
00088 // must have the name <split_leaf>_<splitcat_label> to be picked up. The list
00089 // of pre-supplied leafs may be partial, any missing split leafs will be auto
00090 // generated.
00091 //
00092 // Another common construction is to have two prototype PDFs, each to be customized
00093 // by a separate customizer instance, that share parameters. To ensure that
00094 // the customized clones also share their respective split leafs, i.e.
00095 //
00096 //   PDF1(x,y;A) and PDF2(z,A)   ---> PDF1_run1(x,y,A_run1) and PDF2_run1(x,y,A_run1)
00097 //                                    PDF1_run2(x,y,A_run2) and PDF2_run2(x,y,A_run2)
00098 //
00099 // feed the same split leaf list into both customizers. In that case the second customizer
00100 // will pick up the split leafs instantiated by the first customizer and the link between
00101 // the two PDFs is retained
00102 //
00103 //
00104 
00105 
00106 #include "RooFit.h"
00107 
00108 #include "TClass.h"
00109 #include "TStopwatch.h"
00110 
00111 #include "RooAbsCategoryLValue.h" 
00112 #include "RooAbsCategory.h"
00113 #include "RooAbsArg.h"
00114 #include "RooAbsPdf.h"
00115 #include "RooArgSet.h"
00116 #include "RooArgList.h"
00117 #include "RooMsgService.h"
00118 
00119 #include "RooCustomizer.h"
00120 
00121 #include "Riostream.h"
00122 #include "RooWorkspace.h"
00123 #include "RooGlobalFunc.h"
00124 
00125 ClassImp(RooCustomizer) 
00126 ;
00127 
00128 
00129 static Int_t init()
00130 {
00131   RooFactoryWSTool::IFace* iface = new RooCustomizer::CustIFace ;
00132   RooFactoryWSTool::registerSpecial("EDIT",iface) ;
00133   return 0 ;
00134 }
00135 static Int_t dummy = init() ;
00136 
00137 
00138 
00139 //_____________________________________________________________________________
00140 RooCustomizer::RooCustomizer(const RooAbsArg& pdf, const RooAbsCategoryLValue& masterCat, RooArgSet& splitLeafs, RooArgSet* splitLeafsAll) :
00141   TNamed(pdf.GetName(),pdf.GetTitle()),
00142   _sterile(kFALSE),
00143   _owning(kTRUE),
00144   _masterPdf((RooAbsArg*)&pdf), 
00145   _masterCat((RooAbsCategoryLValue*)&masterCat), 
00146   _masterBranchList("masterBranchList"), 
00147   _masterLeafList("masterLeafList"), 
00148   _internalCloneBranchList("cloneBranchList"),
00149   _cloneNodeListAll(splitLeafsAll),
00150   _cloneNodeListOwned(&splitLeafs)
00151 {
00152   // Constructor with a prototype and masterCat index category.
00153   // Customizers created by this constructor offer offer both the
00154   // replaceArg() and splitArg() functionality. All nodes created in
00155   // the customization process are added to the splitLeafs set.
00156   // If the customizer is owning, the splitLeafs set will become
00157   // owner of all created objects by the customizer
00158   // 
00159 
00160   _masterBranchList.setHashTableSize(1000) ;
00161   _masterLeafList.setHashTableSize(1000) ;
00162 
00163   _cloneBranchList = &_internalCloneBranchList ;
00164   _cloneBranchList->setHashTableSize(1000) ;
00165 
00166   initialize() ;
00167 }
00168 
00169 
00170 
00171 //_____________________________________________________________________________
00172 RooCustomizer::RooCustomizer(const RooAbsArg& pdf, const char* name) :
00173   TNamed(pdf.GetName(),pdf.GetTitle()),
00174   _sterile(kTRUE), 
00175   _owning(kFALSE),
00176   _name(name),
00177   _masterPdf((RooAbsArg*)&pdf), 
00178   _masterCat(0), 
00179   _masterBranchList("masterBranchList"), 
00180   _masterLeafList("masterLeafList"), 
00181   _internalCloneBranchList("cloneBranchList"),
00182   _cloneNodeListAll(0),
00183   _cloneNodeListOwned(0)
00184 {
00185   // Sterile Constructor. Customizers created by this constructor
00186   // offer only the replace() method. The supplied 'name' is used as
00187   // suffix for any cloned branch nodes
00188 
00189   _masterBranchList.setHashTableSize(1000) ;
00190   _masterLeafList.setHashTableSize(1000) ;
00191 
00192   _cloneBranchList = &_internalCloneBranchList ;
00193   _cloneBranchList->setHashTableSize(1000) ;
00194 
00195   initialize() ;
00196 }
00197 
00198 
00199 
00200 
00201 //_____________________________________________________________________________
00202 void RooCustomizer::initialize() 
00203 {
00204   // Initialize the customizer
00205 
00206   _masterPdf->leafNodeServerList(&_masterLeafList) ;
00207   _masterPdf->branchNodeServerList(&_masterBranchList) ;
00208 
00209   _masterLeafListIter = _masterLeafList.createIterator() ;
00210   _masterBranchListIter = _masterBranchList.createIterator() ;
00211 }
00212 
00213 
00214 
00215 //_____________________________________________________________________________
00216 RooCustomizer::~RooCustomizer() 
00217 {
00218   // Destructor
00219 
00220   delete _masterLeafListIter ;
00221   delete _masterBranchListIter ;
00222 
00223 }
00224 
00225 
00226   
00227 
00228 //_____________________________________________________________________________
00229 void RooCustomizer::splitArgs(const RooArgSet& set, const RooAbsCategory& splitCat) 
00230 {
00231   // Split all arguments in 'set' into individualized clones for each
00232   // defined state of 'splitCat'. The 'splitCats' category must be
00233   // subset of or equal to the master category supplied in the
00234   // customizer constructor.
00235   //
00236   // Splitting is only available on customizers created with a master index category
00237 
00238   if (_sterile) {
00239     coutE(InputArguments) << "RooCustomizer::splitArgs(" << _name 
00240                           << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
00241     return ;
00242   }
00243   TIterator* iter = set.createIterator() ;
00244   RooAbsArg* arg ;
00245   while((arg=(RooAbsArg*)iter->Next())){
00246     splitArg(*arg,splitCat) ;
00247   }
00248   delete iter ;
00249 }
00250 
00251 
00252 
00253 //_____________________________________________________________________________
00254 void RooCustomizer::splitArg(const RooAbsArg& arg, const RooAbsCategory& splitCat) 
00255 {
00256   // Split all argument 'arg' into individualized clones for each
00257   // defined state of 'splitCat'. The 'splitCats' category must be
00258   // subset of or equal to the master category supplied in the
00259   // customizer constructor.
00260   //
00261   // Splitting is only available on customizers created with a master index category
00262 
00263   if (_splitArgList.FindObject(arg.GetName())) {
00264     coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple splitting rules defined for " 
00265                           << arg.GetName() << " only using first rule" << endl ;
00266     return ;
00267   }
00268 
00269   if (_sterile) {
00270     coutE(InputArguments) << "RooCustomizer::splitArg(" << _name 
00271          << ") ERROR cannot set spitting rules on this sterile customizer" << endl ;
00272     return ;
00273   }
00274 
00275   _splitArgList.Add((RooAbsArg*)&arg) ;
00276   _splitCatList.Add((RooAbsCategory*)&splitCat) ;
00277 }
00278 
00279 
00280 
00281 //_____________________________________________________________________________
00282 void RooCustomizer::replaceArg(const RooAbsArg& orig, const RooAbsArg& subst) 
00283 {
00284   // Replace any occurence of arg 'orig' with arg 'subst'
00285 
00286   if (_replaceArgList.FindObject(orig.GetName())) {
00287     coutE(InputArguments) << "RooCustomizer(" << GetName() << ") ERROR: multiple replacement rules defined for " 
00288          << orig.GetName() << " only using first rule" << endl ;
00289     return ;
00290   }
00291 
00292   _replaceArgList.Add((RooAbsArg*)&orig) ;
00293   _replaceSubList.Add((RooAbsArg*)&subst) ;
00294 }
00295 
00296 
00297 
00298 //_____________________________________________________________________________
00299 RooAbsArg* RooCustomizer::build(Bool_t verbose) 
00300 {
00301   // Build a clone of the prototype executing all registered 'replace' rules
00302   // If verbose is set a message is printed for each leaf or branch node
00303   // modification. The returned head node owns all cloned branch nodes
00304   // that were created in the cloning proces
00305 
00306   // Execute build
00307   RooAbsArg* ret =  doBuild(_name,verbose) ;
00308 
00309   // Make root object own all cloned nodes
00310 
00311   // First make list of all objects that were created
00312   RooArgSet allOwned ;
00313   if (_cloneNodeListOwned) {
00314     allOwned.add(*_cloneNodeListOwned) ;
00315   }
00316   allOwned.add(*_cloneBranchList) ;
00317 
00318   // Remove head node from list
00319   allOwned.remove(*ret) ;
00320 
00321   // If list with owned objects is not empty, assign
00322   // head node as owner
00323   if (allOwned.getSize()>0) {
00324     ret->addOwnedComponents(allOwned) ;
00325   }
00326 
00327   return ret ;
00328 }
00329 
00330 
00331 
00332 //_____________________________________________________________________________
00333 RooAbsArg* RooCustomizer::build(const char* masterCatState, Bool_t verbose) 
00334 {
00335   // Build a clone of the prototype executing all registered 'replace'
00336   // rules and 'split' rules for the masterCat state named
00337   // 'masterCatState'.  If verbose is set a message is printed for
00338   // each leaf or branch node modification. The returned composite arg
00339   // is owned by the customizer.  This function cannot be called on
00340   // customizer build with the sterile constructor.
00341 
00342   if (_sterile) {
00343     coutE(InputArguments) << "RooCustomizer::build(" << _name 
00344                           << ") ERROR cannot use leaf spitting build() on this sterile customizer" << endl ;
00345     return 0 ;
00346   }
00347 
00348   // Set masterCat to given state
00349   if (_masterCat->setLabel(masterCatState)) {
00350     coutE(InputArguments) << "RooCustomizer::build(" << _masterPdf->GetName() << "): ERROR label '" << masterCatState 
00351                           << "' not defined for master splitting category " << _masterCat->GetName() << endl ;
00352     return 0 ;
00353   }
00354 
00355   return doBuild(masterCatState,verbose) ;
00356 }
00357 
00358 
00359 
00360 //_____________________________________________________________________________
00361 RooAbsArg* RooCustomizer::doBuild(const char* masterCatState, Bool_t verbose) 
00362 {
00363   // Back-end implementation of the p.d.f building functionality
00364 
00365   // Find nodes that must be split according to provided description, Clone nodes, change their names
00366   RooArgSet masterNodesToBeSplit("masterNodesToBeSplit") ;
00367   RooArgSet masterNodesToBeReplaced("masterNodesToBeReplaced") ;
00368   RooArgSet masterReplacementNodes("masterReplacementNodes") ;
00369   RooArgSet clonedMasterNodes("clonedMasterNodes") ;
00370 
00371   masterNodesToBeSplit.setHashTableSize(1000) ;
00372   masterNodesToBeReplaced.setHashTableSize(1000) ;
00373   masterReplacementNodes.setHashTableSize(1000) ;
00374   clonedMasterNodes.setHashTableSize(1000) ;
00375 
00376   _masterLeafListIter->Reset() ;
00377   RooAbsArg* node ;
00378 
00379   RooArgSet nodeList(_masterLeafList) ;
00380   nodeList.setHashTableSize(1000) ;
00381 
00382   nodeList.add(_masterBranchList) ;
00383   TIterator* nIter = nodeList.createIterator() ;
00384 
00385 //   cout << "loop over " << nodeList.getSize() << " nodes" << endl ;
00386   while((node=(RooAbsArg*)nIter->Next())) {
00387     RooAbsArg* theSplitArg = !_sterile?(RooAbsArg*) _splitArgList.FindObject(node->GetName()):0 ;
00388     if (theSplitArg) {
00389       RooAbsCategory* splitCat = (RooAbsCategory*) _splitCatList.At(_splitArgList.IndexOf(theSplitArg)) ;
00390       if (verbose) {
00391         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() 
00392                               << "): tree node " << node->GetName() << " is split by category " << splitCat->GetName() << endl ;
00393       }
00394       
00395       TString newName(node->GetName()) ;
00396       newName.Append("_") ;
00397       newName.Append(splitCat->getLabel()) ;    
00398 
00399       // Check if this node instance already exists
00400       RooAbsArg* specNode = _cloneNodeListAll ? _cloneNodeListAll->find(newName) : _cloneNodeListOwned->find(newName) ;
00401       if (specNode) {
00402 
00403         // Copy instance to one-time use list for this build
00404         clonedMasterNodes.add(*specNode) ;
00405         if (verbose) {
00406           coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() 
00407                                 << ") Adding existing node specialization " << newName << " to clonedMasterNodes" << endl ;
00408         }
00409 
00410         // Affix attribute with old name to clone to support name changing server redirect
00411         TString nameAttrib("ORIGNAME:") ;
00412         nameAttrib.Append(node->GetName()) ;
00413         specNode->setAttribute(nameAttrib) ;
00414 
00415       } else {
00416 
00417         if (node->isDerived()) {
00418           coutW(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() 
00419                                 << "): WARNING: branch node " << node->GetName() << " is split but has no pre-defined specializations" << endl ;
00420         }
00421 
00422         TString newTitle(node->GetTitle()) ;
00423         newTitle.Append(" (") ;
00424         newTitle.Append(splitCat->getLabel()) ;
00425         newTitle.Append(")") ;
00426       
00427         // Create a new clone
00428         RooAbsArg* clone = (RooAbsArg*) node->Clone(newName.Data()) ;
00429         clone->SetTitle(newTitle) ;
00430 
00431         // Affix attribute with old name to clone to support name changing server redirect
00432         TString nameAttrib("ORIGNAME:") ;
00433         nameAttrib.Append(node->GetName()) ;
00434         clone->setAttribute(nameAttrib) ;
00435 
00436         // Add to one-time use list and life-time use list
00437         clonedMasterNodes.add(*clone) ;
00438         if (_owning) {
00439           _cloneNodeListOwned->addOwned(*clone) ;       
00440         } else {
00441           _cloneNodeListOwned->add(*clone) ;    
00442         }
00443         if (_cloneNodeListAll) {
00444           _cloneNodeListAll->add(*clone) ;      
00445         }       
00446       }
00447       masterNodesToBeSplit.add(*node) ;     
00448     }
00449 
00450     RooAbsArg* ReplaceArg = (RooAbsArg*) _replaceArgList.FindObject(node->GetName()) ;
00451     if (ReplaceArg) {
00452       RooAbsArg* substArg = (RooAbsArg*) _replaceSubList.At(_replaceArgList.IndexOf(ReplaceArg)) ;
00453       if (verbose) {
00454         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() 
00455                               << "): tree node " << node->GetName() << " will be replaced by " << substArg->GetName() << endl ;
00456       }
00457 
00458       // Affix attribute with old name to support name changing server redirect
00459       TString nameAttrib("ORIGNAME:") ;
00460       nameAttrib.Append(node->GetName()) ;
00461       substArg->setAttribute(nameAttrib) ;
00462 
00463       // Add to list
00464       masterNodesToBeReplaced.add(*node) ;
00465       masterReplacementNodes.add(*substArg) ;
00466     }
00467   }
00468   delete nIter ;
00469 
00470   // Find branches that are affected by splitting and must be cloned
00471   RooArgSet masterBranchesToBeCloned("masterBranchesToBeCloned") ;
00472   masterBranchesToBeCloned.setHashTableSize(1000) ;
00473   _masterBranchListIter->Reset() ;
00474   RooAbsArg* branch ;
00475   while((branch=(RooAbsArg*)_masterBranchListIter->Next())) {
00476     
00477     // If branch is split itself, don't handle here
00478     if (masterNodesToBeSplit.find(branch->GetName())) {
00479       if (verbose) {
00480         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already split" << endl ;
00481       }
00482       continue ;
00483     }
00484     if (masterNodesToBeReplaced.find(branch->GetName())) {
00485       if (verbose) {
00486         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " << branch->GetName() << " is already replaced" << endl ;
00487       }
00488       continue ;
00489     }
00490 
00491     if (branch->dependsOn(masterNodesToBeSplit)) {
00492       if (verbose) {
00493         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " 
00494                               << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a split parameter" << endl ;
00495       }
00496       masterBranchesToBeCloned.add(*branch) ;
00497     } else if (branch->dependsOn(masterNodesToBeReplaced)) {
00498       if (verbose) {
00499         coutI(ObjectHandling) << "RooCustomizer::build(" << _masterPdf->GetName() << ") Branch node " 
00500                               << branch->IsA()->GetName() << "::" << branch->GetName() << " cloned: depends on a replaced parameter" << endl ;
00501       }
00502       masterBranchesToBeCloned.add(*branch) ;
00503     }
00504   }
00505 
00506   // Clone branches, changes their names 
00507   RooAbsArg* cloneTopPdf = 0;
00508   RooArgSet clonedMasterBranches("clonedMasterBranches") ;
00509   clonedMasterBranches.setHashTableSize(1000) ;
00510   TIterator* iter = masterBranchesToBeCloned.createIterator() ;
00511   while((branch=(RooAbsArg*)iter->Next())) {
00512     TString newName(branch->GetName()) ;
00513     newName.Append("_") ;
00514     newName.Append(masterCatState) ;
00515 
00516     // Affix attribute with old name to clone to support name changing server redirect
00517     RooAbsArg* clone = (RooAbsArg*) branch->Clone(newName.Data()) ;
00518     TString nameAttrib("ORIGNAME:") ;
00519     nameAttrib.Append(branch->GetName()) ;
00520     clone->setAttribute(nameAttrib) ;
00521 
00522     clonedMasterBranches.add(*clone) ;      
00523 
00524     // Save pointer to clone of top-level pdf
00525     if (branch==_masterPdf) cloneTopPdf=(RooAbsArg*)clone ;
00526   }
00527   delete iter ;
00528   if (_owning) {
00529     _cloneBranchList->addOwned(clonedMasterBranches) ;
00530   } else {
00531     _cloneBranchList->add(clonedMasterBranches) ;
00532   }
00533     
00534   // Reconnect cloned branches to each other and to cloned nodess
00535   iter = clonedMasterBranches.createIterator() ;
00536   while((branch=(RooAbsArg*)iter->Next())) {
00537     branch->redirectServers(clonedMasterBranches,kFALSE,kTRUE) ;
00538     branch->redirectServers(clonedMasterNodes,kFALSE,kTRUE) ;
00539     branch->redirectServers(masterReplacementNodes,kFALSE,kTRUE) ;
00540   }
00541   delete iter ;  
00542 
00543   return cloneTopPdf?cloneTopPdf:_masterPdf ;
00544 }
00545 
00546 
00547 //_____________________________________________________________________________
00548 void RooCustomizer::printName(ostream& os) const 
00549 {
00550   // Print name of customizer
00551   os << GetName() ;
00552 }
00553 
00554 
00555 //_____________________________________________________________________________
00556 void RooCustomizer::printTitle(ostream& os) const 
00557 {
00558   // Print title of customizer
00559   os << GetTitle() ;
00560 }
00561 
00562 
00563 //_____________________________________________________________________________
00564 void RooCustomizer::printClassName(ostream& os) const 
00565 {
00566   // Print class name of customizer
00567   os << IsA()->GetName() ;
00568 }
00569 
00570 
00571 //_____________________________________________________________________________
00572 void RooCustomizer::printArgs(ostream& os) const 
00573 {
00574   // Print arguments of customizer, i.e. input p.d.f and input master category (if any)
00575   os << "[ masterPdf=" << _masterPdf->GetName() ;
00576   if (_masterCat) {
00577     os << " masterCat=" << _masterCat->GetName() ;
00578   }
00579   os << " ]" ;
00580 }
00581 
00582 
00583 
00584 //_____________________________________________________________________________
00585 void RooCustomizer::printMultiline(ostream& os, Int_t /*content*/, Bool_t /*verbose*/, TString indent) const
00586 {
00587   // Print customizer configuration details
00588 
00589   os << indent << "RooCustomizer for " << _masterPdf->GetName() << (_sterile?" (sterile)":"") << endl ;
00590 
00591   Int_t i, nsplit = _splitArgList.GetSize() ;
00592   if (nsplit>0) {
00593     os << indent << "  Splitting rules:" << endl ;
00594     for (i=0 ; i<nsplit ; i++) {
00595       os << indent << "   " << _splitArgList.At(i)->GetName() << " is split by " << _splitCatList.At(i)->GetName() << endl ;
00596     }
00597   }
00598 
00599   Int_t nrepl = _replaceArgList.GetSize() ;
00600   if (nrepl>0) {
00601     os << indent << "  Replacement rules:" << endl ;
00602     for (i=0 ; i<nrepl ; i++) {
00603       os << indent << "   " << _replaceSubList.At(i)->GetName() << " replaces " << _replaceArgList.At(i)->GetName() << endl ;
00604     }
00605   }
00606   
00607   return ;
00608 }
00609 
00610 
00611 
00612 //_____________________________________________________________________________
00613 void RooCustomizer::setCloneBranchSet(RooArgSet& cloneBranchSet) 
00614 {
00615   // Install the input RooArgSet as container in which all cloned branches
00616   // will be stored
00617 
00618   _cloneBranchList = &cloneBranchSet ;
00619   _cloneBranchList->setHashTableSize(1000) ;
00620 }
00621 
00622 
00623 
00624 
00625 //_____________________________________________________________________________
00626 std::string RooCustomizer::CustIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args) 
00627 {
00628   // Check number of arguments
00629   if (args.size()<2) {
00630     throw string(Form("RooCustomizer::CustIFace::create() ERROR: expect at least 2 arguments for EDIT: the input object and at least one $Replace() rule")) ;
00631   }
00632 
00633   if (string(typeName)!="EDIT") {
00634     throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown type requested: %s",typeName)) ;
00635   }
00636 
00637 
00638   // Check that first arg exists as RooAbsArg
00639   RooAbsArg* arg = ft.ws().arg(args[0].c_str()) ;
00640   if (!arg) {
00641     throw string(Form("RooCustomizer::CustIFace::create() ERROR: input RooAbsArg %s does not exist",args[0].c_str())) ;
00642   }
00643 
00644   // Create a customizer
00645   RooCustomizer cust(*arg,instanceName) ;
00646   
00647   for (unsigned int i=1 ; i<args.size() ; i++) {
00648     char buf[1024] ;
00649     strlcpy(buf,args[i].c_str(),1024) ;
00650     char* sep = strchr(buf,'=') ;
00651     if (!sep) {
00652       throw string(Form("RooCustomizer::CustIFace::create() ERROR: unknown argument: %s, expect form orig=subst",args[i].c_str())) ;
00653     }
00654     *sep = 0 ;    
00655     RooAbsArg* orig = ft.ws().arg(buf) ;
00656     RooAbsArg* subst = ft.ws().arg(sep+1) ;
00657     if (!orig) {
00658       throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() input RooAbsArg %s does not exist",buf)) ;
00659     }
00660     if (!subst) {
00661       throw string(Form("RooCustomizer::CustIFace::create() ERROR: $Replace() input RooAbsArg %s does not exist",sep+1)) ;
00662     }
00663     cust.replaceArg(*orig,*subst) ;
00664   }
00665 
00666   // Build the desired edited object
00667   RooAbsArg* targ = cust.build(kFALSE)  ;
00668   if (!targ) {
00669     throw string(Form("RooCustomizer::CustIFace::create() ERROR in customizer build, object %snot created",instanceName)) ;
00670   }
00671 
00672   // Set the desired name of the top level node
00673   targ->SetName(instanceName) ;
00674 
00675   // Import the object into the workspace
00676   ft.ws().import(*targ,RooFit::Silence()) ;
00677       
00678   return string(instanceName) ;
00679 }

Generated on Tue Jul 5 15:06:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1