RooSimWSTool.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooSimWSTool.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 // Class RooSimWSTool is a tool operating on RooWorkspace objects that
00020 // can clone p.d.f.s into a series of variations that are joined together
00021 // into a RooSimultanous p.d.f.
00022 //
00023 // The simplest use case to to take a workspace p.d.f as prototype and
00024 // 'split' a parameter of that p.d.f into two specialized parameters
00025 // depending on a category in the dataset. 
00026 // 
00027 // For example, given a Gaussian
00028 // p.d.f G(x,m,s) we want to construct a G_a(x,m_a,s) and a G_b(x,m_b,s)
00029 // with different mean parameters to be fit to a dataset with observables
00030 // (x,c) where c is a category with states 'a' and 'b'
00031 //
00032 // Using RooSimWSTool one can create a simultaneous p.d.f from G_a and G_b
00033 // from G with the following command
00034 //
00035 //   RooSimWSTool wst(wspace) ;
00036 //   wst.build("G_sim","G",SplitParam("m","c")) ;
00037 //
00038 // From this simple example one can go to builds of arbitrary complexity
00039 // by specifying multiple SplitParam arguments on multiple parameters
00040 // involving multiple splitting categories. Splits can also be performed
00041 // in the product multiple categories, e.g. 
00042 //
00043 //      SplitParam("m","c,d")) ;
00044 //
00045 // splits parameter m in the product of states of c and d. Another possibility
00046 // is the 'constrained' split which clones the parameter for all but one state
00047 // and insert a formula specialization in a chosen state that evaluates
00048 // to 1 - sum_i(a_i) where a_i are all other specializations. For example,
00049 // given a category c with state "A","B","C","D" the specification
00050 //
00051 //     SplitParamConstrained("m","c","D")
00052 //
00053 // will result in parameters m_A,m_B,m_C and a formula expression m_D
00054 // that evaluates to (1-(m_A+m_B+m_C)). Constrained split can also be
00055 // specified in product of categories. In that case the name of the
00056 // remainder state follows the syntax "{State1;State2}" where State1 and
00057 // State2 are the state names of the two spitting categories.
00058 //
00059 // The examples so far deal with a single prototype p.d.f. It is also
00060 // possible to build with multiple prototype p.d.fs by specifying a 
00061 // mapping between the prototype to use and the names of states of
00062 // a 'master' splitting category. To specify these configurations
00063 // an intermediate MultiBuildConfig must be composed with all
00064 // the necessary specifications. For example, this code
00065 // 
00066 //  RooSimWSTool::MultiBuildConfig mbc("mc") ;
00067 //  mbc.addPdf("I","G",SplitParam("m,s","c")) ;
00068 //  mbc.addPdf("II,III","F",SplitParam("a","c,d")) ;
00069 //
00070 // configures a build with two prototype p.d.f.s G and F.
00071 // Prototype G is used for state "I" of master split category
00072 // mc and prototype F is used for states "II" and "III" of
00073 // master split category mc. Furthermore parameters m,s of prototype G are split
00074 // in category c while parameter a of prototype F is split in
00075 // the product of categories c and d. The actual build is then
00076 // performed by passing the build configuration to RooSimWSTool, e.g.
00077 //
00078 //  wst.build("MASTER",mbc) ;
00079 //
00080 // By default, a specialization is built for each permutation of
00081 // states of the spitting categories that are used. It is possible
00082 // to restrict the building of specialized p.d.f to a subset of states
00083 // by adding a restriction on the number of states to build as follows
00084 //
00085 //  mbc.restrictBuild("c","A,B") ;  
00086 //
00087 // The restrictBuild method can be called multiple times, but at most
00088 // once for each used splitting category. For simple builds with a single
00089 // prototype, restriction can be specified with a Restrict() argument
00090 // on the build command line
00091 //
00092 
00093 
00094 #include "RooFit.h"
00095 #include "RooSimWSTool.h"
00096 #include "RooMsgService.h"
00097 #include "RooCategory.h"
00098 #include "RooRealVar.h"
00099 #include "RooAbsPdf.h"
00100 #include "RooStringVar.h"
00101 #include "RooSuperCategory.h"
00102 #include "RooCatType.h"
00103 #include "RooCustomizer.h"
00104 #include "RooMultiCategory.h"
00105 #include "RooSimultaneous.h"
00106 #include "RooGlobalFunc.h"
00107 #include "RooFracRemainder.h"
00108 #include "RooFactoryWSTool.h"
00109 
00110 ClassImp(RooSimWSTool) 
00111 ClassImp(RooSimWSTool::BuildConfig) 
00112 ClassImp(RooSimWSTool::MultiBuildConfig) 
00113 ClassImp(RooSimWSTool::SplitRule) 
00114 ClassImp(RooSimWSTool::ObjBuildConfig) 
00115 ClassImp(RooSimWSTool::ObjSplitRule) 
00116 ;
00117 
00118 using namespace std ;
00119 
00120 
00121 static Int_t init()
00122 {
00123   RooFactoryWSTool::IFace* iface = new RooSimWSTool::SimWSIFace ;
00124   RooFactoryWSTool::registerSpecial("SIMCLONE",iface) ;
00125   RooFactoryWSTool::registerSpecial("MSIMCLONE",iface) ;
00126   return 0 ;
00127 }
00128 static Int_t dummy = init() ;
00129 
00130 
00131 //_____________________________________________________________________________
00132 RooSimWSTool::RooSimWSTool(RooWorkspace& ws) : _ws(&ws) 
00133 {
00134   // Constructor of SimWSTool on given workspace. All input is taken from the workspace
00135   // All output is stored in the workspace
00136 }
00137 
00138 
00139 
00140 //_____________________________________________________________________________
00141 RooSimWSTool::~RooSimWSTool() 
00142 {
00143   // Destructor
00144 }
00145 
00146 
00147 
00148 //_____________________________________________________________________________
00149 RooSimultaneous* RooSimWSTool::build(const char* simPdfName, const char* protoPdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
00150                                         const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
00151 {
00152   // Build a RooSimultaneous p.d.f with name simPdfName from cloning specializations of protytpe p.d.f protoPdfName.
00153   // The following named arguments are supported
00154   //
00155   // SplitParam(varname, catname)                   -- Split parameter(s) with given name(s) in category(s) with given names
00156   // SplitParam(var, cat)                           -- Split given parameter(s) in givem category(s) 
00157   // SplitParamConstrained(vname, cname, remainder) -- Make constrained split in parameter(s) with given name(s) in category(s) with given names
00158   //                                                   putting remainder fraction formula in state with name "remainder"
00159   // SplitParamConstrained(var,cat,remainder)       -- Make constrained split in parameter(s) with given name(s) in category(s) with given names
00160   //                                                   putting remainder fraction formula in state with name "remainder"
00161   // Restrict(catName,stateNameList)                -- Restrict build by only considered listed state names of category with given name
00162 
00163   BuildConfig bc(protoPdfName,arg1,arg2,arg3,arg4,arg5,arg6) ;
00164   return build(simPdfName,bc) ;
00165 }
00166 
00167 
00168 
00169 //_____________________________________________________________________________
00170 RooSimultaneous* RooSimWSTool::build(const char* simPdfName,BuildConfig& bc, Bool_t verbose) 
00171 {
00172   // Build a RooSimultaneous p.d.f with name simPdfName from cloning specializations of protytpe p.d.f protoPdfName.
00173   // Use the provided BuildConfig or MultiBuildConfig object to configure the build
00174 
00175   ObjBuildConfig* obc = validateConfig(bc) ;
00176   if (!obc) return 0 ;
00177   
00178   if (verbose) {
00179     obc->print() ;
00180   }
00181   
00182   RooSimultaneous* ret =  executeBuild(simPdfName,*obc,verbose) ;
00183 
00184   delete obc ;
00185   return ret ;
00186 }
00187 
00188 
00189 
00190 //_____________________________________________________________________________
00191 RooSimWSTool::ObjBuildConfig* RooSimWSTool::validateConfig(BuildConfig& bc)
00192 {
00193   // Validate build configuration. If not syntax errors or missing objects are found,
00194   // return an ObjBuildConfig in which all names are replaced with object pointers.
00195 
00196   // Create empty object version of build config
00197   ObjBuildConfig* obc = new ObjBuildConfig ;
00198 
00199   if (bc._masterCatName.length()>0) {
00200     obc->_masterCat = _ws->cat(bc._masterCatName.c_str()) ;
00201     if (!obc->_masterCat) {
00202       coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName() 
00203                             << " does not contain a category named " << bc._masterCatName 
00204                             << " that was designated as master index category in the build configuration" << endl ;
00205       delete obc ;
00206       return 0 ;
00207     }
00208   } else {
00209     obc->_masterCat = 0 ;
00210   }
00211   
00212   map<string,SplitRule>::iterator pdfiter ;
00213   // Check that we have the p.d.f.s
00214   for (pdfiter = bc._pdfmap.begin() ; pdfiter != bc._pdfmap.end() ; ++pdfiter) {    
00215 
00216     // Check that p.d.f exists
00217     RooAbsPdf* pdf = _ws->pdf(pdfiter->second.GetName()) ;
00218     if (!pdf) {
00219       coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName() 
00220                             << " does not contain a pdf named " << pdfiter->second.GetName() << endl ;
00221       delete obc ;
00222       return 0 ;
00223     }      
00224 
00225     // Create empty object version of split rule set
00226     ObjSplitRule osr ;
00227 
00228     // Convert names of parameters and splitting categories to objects in workspace, fill object split rule
00229     SplitRule& sr = pdfiter->second ;
00230 
00231     map<string, pair<list<string>,string> >::iterator pariter ;
00232     for (pariter=sr._paramSplitMap.begin() ; pariter!=sr._paramSplitMap.end() ; ++pariter) {
00233       
00234       // Check that variable with given name exists in workspace
00235       RooAbsArg* farg = _ws->fundArg(pariter->first.c_str()) ;
00236       if (!farg) {
00237         coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName() 
00238                               << " does not contain a variable named " << pariter->first.c_str() 
00239                               << " as specified in splitting rule of parameter " << pariter->first << " of p.d.f " << pdf << endl ;
00240         delete obc ;
00241         return 0 ;
00242       } 
00243       
00244       // Check that given variable is indeed related to given p.d.f
00245       if (!pdf->dependsOn(*farg)) {
00246         coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: specified parameter " << pariter->first 
00247                               << " in split is not function of p.d.f " << pdf->GetName() << endl ;
00248         delete obc ;
00249         return 0 ;
00250       }
00251       
00252       
00253       RooArgSet splitCatSet ;
00254       list<string>::iterator catiter ;
00255       for (catiter = pariter->second.first.begin() ; catiter!=pariter->second.first.end() ; ++catiter) {
00256         RooAbsCategory* cat = _ws->catfunc(catiter->c_str()) ;
00257         if (!cat) {
00258           coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName() 
00259                                 << " does not contain a category named " << catiter->c_str() 
00260                                 << " as specified in splitting rule of parameter " << pariter->first << " of p.d.f " << pdf << endl ;
00261           delete obc ;
00262           return 0 ;
00263         }
00264         splitCatSet.add(*cat) ;
00265       }      
00266 
00267       // Check if composite splitCatSet does not contain category functions that depend on other categories used in the same split
00268       TIterator* iter = splitCatSet.createIterator() ;
00269       RooAbsArg* arg ;
00270       while((arg=(RooAbsArg*)iter->Next())) {
00271         RooArgSet tmp(splitCatSet) ;
00272         tmp.remove(*arg) ;
00273         if (arg->dependsOnValue(tmp)) {
00274           coutE(InputArguments) << "RooSimWSTool::build(" << GetName() << ") ERROR: Ill defined split: splitting category function " << arg->GetName() 
00275                                 << " used in composite split " << splitCatSet << " of parameter " << farg->GetName() << " of pdf " << pdf->GetName() 
00276                                 << " depends on one or more of the other splitting categories in the composite split" << endl ;
00277           delete obc ;
00278           delete iter ;
00279           return 0 ;
00280         }
00281       }
00282       delete iter ;
00283 
00284       // If a constrained split is specified, check that split parameter is a real-valued type
00285       if (pariter->second.second.size()>0) {
00286         if (!dynamic_cast<RooAbsReal*>(farg)) {
00287           coutE(InputArguments) << "RooSimWSTool::build(" << GetName() << ") ERROR: Constrained split specified in non real-valued parameter " << farg->GetName() << endl ;
00288           delete obc ;
00289           return 0 ;
00290         }
00291       }
00292 
00293       // Fill object build config with object split rule
00294       osr._paramSplitMap[farg].first.add(splitCatSet) ;
00295       osr._paramSplitMap[farg].second = pariter->second.second ;
00296 
00297       // For multi-pdf configurations, check that the master index state name associated with this p.d.f exists as a state in the master category
00298       if (obc->_masterCat) {
00299         list<string>::iterator misi ;
00300         for (misi=sr._miStateNameList.begin() ; misi!=sr._miStateNameList.end() ; ++misi) {
00301           const RooCatType* ctype = obc->_masterCat->lookupType(misi->c_str(),kFALSE) ;
00302           if (ctype==0) {         
00303             coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: master index category " << obc->_masterCat->GetName() 
00304                                   << " does not have a state named " << *misi << " which was specified as state associated with p.d.f " 
00305                                   << sr.GetName() << endl ;
00306             delete obc ;
00307             return 0 ;      
00308           }
00309           osr._miStateList.push_back(ctype) ;
00310         }       
00311       }
00312 
00313       // Add specified split cats to global list of all splitting categories
00314       obc->_usedSplitCats.add(splitCatSet,kTRUE) ;
00315       
00316     }
00317     // Need to add clause here for SplitRules without any split (which can happen in MultiBuildConfigs)
00318     if (sr._paramSplitMap.size()==0) {
00319 
00320       if (obc->_masterCat) {
00321         list<string>::iterator misi ;
00322         for (misi=sr._miStateNameList.begin() ; misi!=sr._miStateNameList.end() ; ++misi) {
00323           const RooCatType* ctype = obc->_masterCat->lookupType(misi->c_str(),kFALSE) ;
00324           if (ctype==0) {         
00325             coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: master index category " << obc->_masterCat->GetName() 
00326                                   << " does not have a state named " << *misi << " which was specified as state associated with p.d.f " 
00327                                   << sr.GetName() << endl ;
00328             delete obc ;
00329             return 0 ;      
00330           }
00331           osr._miStateList.push_back(ctype) ;
00332         }       
00333       }
00334     }
00335 
00336     obc->_pdfmap[pdf] = osr ;
00337 
00338   }
00339 
00340   // Check validity of build restriction specifications, if any
00341   map<string,string>::iterator riter ;
00342   for (riter=bc._restr.begin() ; riter!=bc._restr.end() ; ++riter) {
00343     RooCategory* cat = _ws->cat(riter->first.c_str()) ;
00344     if (!cat) {
00345       coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName() 
00346                             << " does not contain a category named " << riter->first
00347                             << " for which build was requested to be restricted to states " << riter->second << endl ;
00348       delete obc ;
00349       return 0 ;
00350     }   
00351 
00352     char buf[4096] ;
00353     list<const RooCatType*> rlist ;
00354     strlcpy(buf,riter->second.c_str(),4096) ;
00355     
00356     char* tok = strtok(buf,"{,}") ;
00357     while(tok) {
00358       const RooCatType* ctype = cat->lookupType(tok,kFALSE) ;
00359       if (!ctype) {
00360         coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: restricted build category " << cat->GetName() 
00361                               << " does not have state " << tok << " as specified in restriction list" << endl ;        
00362         delete obc ;
00363         return 0 ;
00364       }
00365       rlist.push_back(ctype) ;
00366       tok = strtok(0,"{,}") ;
00367     }
00368     
00369     obc->_restr[cat] = rlist ;
00370   }
00371    
00372   return obc ;
00373 }
00374 
00375 
00376 
00377 
00378 //_____________________________________________________________________________
00379 RooSimultaneous* RooSimWSTool::executeBuild(const char* simPdfName, ObjBuildConfig& obc, Bool_t verbose)
00380 {
00381   // Internal build driver from validation ObjBuildConfig.
00382 
00383   RooArgSet cleanupList ;
00384 
00385   RooAbsCategoryLValue* physCat = obc._masterCat ;
00386 
00387   RooArgSet physModelSet ;
00388   map<string,RooAbsPdf*> stateMap ;
00389 
00390   map<RooAbsPdf*,ObjSplitRule>::iterator physIter = obc._pdfmap.begin() ;
00391   while(physIter!=obc._pdfmap.end()) {
00392 
00393     
00394     RooAbsPdf* physModel = physIter->first ;
00395     physModelSet.add(*physModel,kTRUE) ; // silence duplicate insertion warnings
00396 
00397     list<const RooCatType*>::iterator stiter ;
00398     for (stiter=physIter->second._miStateList.begin() ; stiter!=physIter->second._miStateList.end() ; ++stiter) {
00399       stateMap[(*stiter)->GetName()] = physModel ;
00400     }
00401 
00402     // Continue with next mapping
00403     ++physIter ;
00404   }
00405   if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: list of prototype pdfs " << physModelSet << endl ;
00406 
00407   RooArgSet splitCatSet(obc._usedSplitCats) ;
00408   if (physCat) splitCatSet.add(*physCat) ;
00409 
00410   RooArgSet splitCatSetFund ;
00411   TIterator* scsiter = splitCatSet.createIterator() ;
00412   RooAbsCategory* scat ;
00413   while((scat=(RooAbsCategory*)scsiter->Next())) {
00414     if (scat->isFundamental()) {
00415       splitCatSetFund.add(*scat) ;
00416     } else {
00417       RooArgSet* scatvars = scat->getVariables() ;
00418       splitCatSetFund.add(*scatvars) ;
00419       delete scatvars ;
00420     }
00421   }
00422   delete scsiter ;
00423 
00424 
00425   RooAbsCategoryLValue* masterSplitCat ;
00426   if (splitCatSetFund.getSize()>1) {
00427     masterSplitCat = new RooSuperCategory("masterSplitCat","Master splitting category",splitCatSetFund) ;
00428   } else {
00429     masterSplitCat = (RooAbsCategoryLValue*) splitCatSetFund.first() ;
00430   }
00431   if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: list of splitting categories " << splitCatSet << endl ;
00432 
00433   RooArgSet splitNodeListOwned ; // owns all newly created components
00434   RooArgSet splitNodeListAll ; // all leaf nodes, preload with ws contents to auto-connect existing specializations
00435   TList* customizerList = new TList ;
00436 
00437   // Loop over requested physics models and build components
00438   TIterator* physMIter = physModelSet.createIterator() ;
00439   RooAbsPdf* physModel ;
00440   while((physModel=(RooAbsPdf*)physMIter->Next())) {
00441     if (verbose) coutI(ObjectHandling) << "RooSimPdfBuilder::executeBuild: processing prototype pdf " << physModel->GetName() << endl ;
00442 
00443     RooCustomizer* physCustomizer = new RooCustomizer(*physModel,*masterSplitCat,splitNodeListOwned,&splitNodeListAll) ;
00444     customizerList->Add(physCustomizer) ;
00445 
00446     map<RooAbsArg*, pair<RooArgSet,string> >::iterator splitIter ;
00447     for (splitIter = obc._pdfmap[physModel]._paramSplitMap.begin() ; splitIter != obc._pdfmap[physModel]._paramSplitMap.end() ; ++splitIter) {
00448 
00449       // If split is composite, first make multicategory with name 'A,B,C' and insert in WS
00450       
00451       // Construct name of (composite) split category (function)
00452       RooArgSet& splitCatSetTmp = splitIter->second.first ;
00453       string splitName = makeSplitName(splitCatSetTmp) ;
00454 
00455       // If composite split object does not exist yet, create it now
00456       RooAbsCategory* splitCat = _ws->catfunc(splitName.c_str()) ;
00457       if (!splitCat) {
00458         splitCat = new RooMultiCategory(splitName.c_str(),splitName.c_str(),splitCatSetTmp) ;
00459         cleanupList.addOwned(*splitCat) ;
00460         _ws->import(*splitCat,RooFit::Silence(!verbose)) ;
00461       }
00462             
00463       // If remainder category needs to be made, create RFV of appropriate for that and insert in WS
00464       if(splitIter->second.second.size()>0) {
00465         
00466         // Check that specified split name is in fact valid
00467         if (!splitCat->lookupType(splitIter->second.second.c_str())) {
00468           coutE(InputArguments) << "RooSimWSTool::executeBuild(" << GetName() << ") ERROR: name of remainder state for constrained split, '" 
00469                                 << splitIter->second.second << "' , does not match any state name of (composite) split category " << splitCat->GetName() << endl ;
00470           return 0 ;
00471         }
00472 
00473         // First build manually the specializations of all non-remainder states, as the remainder state depends on these
00474         RooArgSet fracLeafList ;
00475         TIterator* sctiter = splitCat->typeIterator() ;
00476         RooCatType* type ;
00477         while((type=(RooCatType*)sctiter->Next())) {
00478           
00479           // Skip remainder state
00480           if (splitIter->second.second == type->GetName()) continue ;
00481                   
00482           // Construct name of split leaf
00483           TString splitLeafName(splitIter->first->GetName()) ;
00484           splitLeafName.Append("_") ;
00485           splitLeafName.Append(type->GetName()) ;
00486           
00487           // Check if split leaf already exists   
00488           RooAbsArg* splitLeaf = _ws->fundArg(splitLeafName) ;
00489           if (!splitLeaf) {
00490             // If not create it now
00491             splitLeaf = (RooAbsArg*) splitIter->first->clone(splitLeafName) ;
00492             _ws->import(*splitLeaf,RooFit::Silence(!verbose)) ;
00493           }
00494           fracLeafList.add(*splitLeaf) ;
00495         }
00496         delete sctiter ;                
00497         
00498 
00499         // Build specialization for remainder state and insert in workspace 
00500         RooFracRemainder* fracRem = new RooFracRemainder(Form("%s_%s",splitIter->first->GetName(),splitIter->second.second.c_str()),"Remainder fraction",fracLeafList) ;
00501         cleanupList.addOwned(*fracRem) ;
00502         _ws->import(*fracRem) ;
00503 
00504       }
00505       
00506 
00507       // Add split definition to customizer
00508       physCustomizer->splitArgs(*splitIter->first,*splitCat) ;
00509     }
00510   }
00511   delete physMIter ;
00512 
00513   // List all existing workspace components as prebuilt items for the customizers at this point
00514   splitNodeListAll.add(_ws->components()) ;
00515 
00516   if (verbose) coutI(ObjectHandling)  << "RooSimWSTool::executeBuild: configured customizers for all prototype pdfs" << endl ;
00517 
00518   // Create fit category from physCat and splitCatList ;
00519   RooArgSet fitCatList ;
00520   if (physCat) fitCatList.add(*physCat) ;
00521 
00522   // Add observables of splitCatSet members, rather than splitCatSet members directly
00523   // as there may be cat->cat functions in here
00524   scsiter = splitCatSet.createIterator() ;
00525   while((scat=(RooAbsCategory*)scsiter->Next())) {
00526     if (scat->isFundamental()) {
00527       fitCatList.add(*scat) ;
00528     } else {
00529       RooArgSet* scatvars = scat->getVariables() ;
00530       fitCatList.add(*scatvars) ;
00531       delete scatvars ;
00532     }
00533   }
00534   delete scsiter ;
00535 
00536 
00537   TIterator* fclIter = fitCatList.createIterator() ;
00538   string mcatname = string(simPdfName) + "_index" ;
00539   RooAbsCategoryLValue* fitCat = 0 ;
00540   if (fitCatList.getSize()>1) {
00541     fitCat = new RooSuperCategory(mcatname.c_str(),mcatname.c_str(),fitCatList) ;
00542     cleanupList.addOwned(*fitCat) ;
00543   } else {
00544     fitCat = (RooAbsCategoryLValue*) fitCatList.first() ;
00545   }
00546 
00547   // Create master PDF 
00548   RooSimultaneous* simPdf = new RooSimultaneous(simPdfName,simPdfName,*fitCat) ;
00549   cleanupList.addOwned(*simPdf) ;
00550   
00551   // Add component PDFs to master PDF
00552   TIterator* fcIter = fitCat->typeIterator() ;
00553 
00554   RooCatType* fcState ;  
00555   while((fcState=(RooCatType*)fcIter->Next())) {
00556     // Select fitCat state
00557     fitCat->setLabel(fcState->GetName()) ;
00558 
00559     // Check if this fitCat state is selected
00560     fclIter->Reset() ;
00561     RooAbsCategory* splitCat ;
00562     Bool_t select(kFALSE) ;
00563     if (obc._restr.size()>0) {
00564       while((splitCat=(RooAbsCategory*)fclIter->Next())) {
00565         // Find selected state list 
00566         
00567         list<const RooCatType*> slist = obc._restr[splitCat] ;    
00568         if (slist.size()==0) {
00569           continue ;
00570         }
00571         
00572         list<const RooCatType*>::iterator sli ;
00573         for (sli=slist.begin() ; sli!=slist.end() ; ++sli) {
00574           if (string(splitCat->getLabel())==(*sli)->GetName()) {
00575             select=kTRUE ;
00576           }
00577         }      
00578       }
00579       if (!select) continue ;
00580     } else {
00581       select = kTRUE ;
00582     }
00583     
00584     // Select appropriate PDF for this physCat state
00585     RooCustomizer* physCustomizer ;
00586     if (physCat) {      
00587       RooAbsPdf* pdf = stateMap[physCat->getLabel()] ;
00588       if (pdf==0) {
00589         continue ;
00590       }
00591       physCustomizer = (RooCustomizer*) customizerList->FindObject(pdf->GetName());  
00592     } else {
00593       physCustomizer = (RooCustomizer*) customizerList->First() ;
00594     }
00595 
00596     if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: Customizing prototype pdf " << physCustomizer->GetName() 
00597                                        << " for mode " << fcState->GetName() << endl ;    
00598 
00599     // Customizer PDF for current state and add to master simPdf
00600     RooAbsPdf* fcPdf = (RooAbsPdf*) physCustomizer->build(masterSplitCat->getLabel(),kFALSE) ;
00601     simPdf->addPdf(*fcPdf,fcState->GetName()) ;
00602   }
00603   delete fcIter ;
00604   
00605   _ws->import(*simPdf,obc._conflProtocol,RooFit::Silence(!verbose)) ;
00606 
00607   // Delete customizers
00608   customizerList->Delete() ;
00609   delete customizerList ;
00610   delete fclIter ;
00611   return (RooSimultaneous*) _ws->pdf(simPdf->GetName()) ;
00612 }
00613 
00614 
00615 
00616 //_____________________________________________________________________________
00617 std::string RooSimWSTool::makeSplitName(const RooArgSet& splitCatSet) 
00618 {
00619   // Construct name of composite split
00620   string name ;
00621 
00622   TIterator* iter = splitCatSet.createIterator() ;
00623   RooAbsArg* arg ;
00624   Bool_t first=kTRUE ;
00625   while((arg=(RooAbsArg*)iter->Next())) {
00626     if (first) {
00627       first=kFALSE;
00628     } else {
00629       name += "," ;
00630     }
00631     name += arg->GetName() ;
00632   }
00633   delete iter ;
00634 
00635   return name ;
00636 }
00637 
00638 
00639 
00640 
00641 //_____________________________________________________________________________
00642 void RooSimWSTool::SplitRule::splitParameter(const char* paramNameList, const char* categoryNameList) 
00643 {
00644   // Specify that parameters names listed in paramNameList be splitted in (product of) category(s)
00645   // listed in categoryNameList
00646 
00647   char paramBuf[4096] ;
00648   char catBuf[4096] ;
00649   strlcpy(paramBuf,paramNameList,4096) ;
00650   strlcpy(catBuf,categoryNameList,4096) ;
00651 
00652   // First parse category list
00653   list<string> catList ;
00654   char* cat = strtok(catBuf,"{,}") ;
00655   while(cat) {
00656     catList.push_back(cat) ;
00657     cat = strtok(0,"{,}") ;
00658   }
00659 
00660   // Now parse parameter list
00661   char* param = strtok(paramBuf,"{,}") ;
00662   while(param) {
00663     _paramSplitMap[param] = pair<list<string>,string>(catList,"") ;
00664     param = strtok(0,"{,}") ;
00665   }
00666 }
00667 
00668 
00669 //_____________________________________________________________________________
00670 void RooSimWSTool::SplitRule::splitParameterConstrained(const char* paramNameList, const char* categoryNameList, const char* remainderStateName) 
00671 {
00672   // Specify that parameters names listed in paramNameList be splitted in constrained way in (product of) category(s)
00673   // listed in categoryNameList and that remainder fraction formula be put in state with name remainderStateName
00674 
00675   char paramBuf[4096] ;
00676   char catBuf[4096] ;
00677   strlcpy(paramBuf,paramNameList,4096) ;
00678   strlcpy(catBuf,categoryNameList,4096) ;
00679 
00680   // First parse category list
00681   list<string> catList ;
00682   char* cat = strtok(catBuf,"{,}") ;
00683   while(cat) {
00684     catList.push_back(cat) ;
00685     cat = strtok(0,"{,}") ;
00686   }
00687 
00688   // Now parse parameter list
00689   char* param = strtok(paramBuf,"{,}") ;
00690   while(param) {
00691     _paramSplitMap[param] = pair<list<string>,string>(catList,remainderStateName) ;
00692     param = strtok(0,"{,}") ;
00693   }
00694 }
00695 
00696 
00697 //_____________________________________________________________________________
00698 void RooSimWSTool::SplitRule::configure(const RooCmdArg& arg1,const RooCmdArg& arg2,const RooCmdArg& arg3,
00699                                            const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
00700 {
00701   // Construct the SplitRule object from a list of named arguments past to RooSimWSTool::build
00702   // This method parses any SplitParam and SplitParamComstrained argument in the list
00703 
00704   list<const RooCmdArg*> cmdList ;  
00705   cmdList.push_back(&arg1) ;  cmdList.push_back(&arg2) ;
00706   cmdList.push_back(&arg3) ;  cmdList.push_back(&arg4) ;
00707   cmdList.push_back(&arg5) ;  cmdList.push_back(&arg6) ;
00708 
00709   list<const RooCmdArg*>::iterator iter ;
00710   for (iter=cmdList.begin() ; iter!=cmdList.end() ; ++iter) {
00711 
00712     if ((*iter)->opcode()==0) continue ;
00713 
00714     string name = (*iter)->opcode() ;
00715 
00716     if (name=="SplitParam") {
00717       splitParameter((*iter)->getString(0),(*iter)->getString(1)) ;
00718     } else if (name=="SplitParamConstrained") {
00719       splitParameterConstrained((*iter)->getString(0),(*iter)->getString(1),(*iter)->getString(2)) ;
00720     }
00721   }
00722 }
00723 
00724 
00725 
00726 
00727 //_____________________________________________________________________________
00728 RooSimWSTool::BuildConfig::BuildConfig(const char* pdfName, SplitRule& sr)
00729 {
00730   // Add prototype p.d.f pdfName to build configuration with associated split rules 'sr'
00731 
00732   internalAddPdf(pdfName,"",sr) ;
00733 }
00734 
00735 
00736 //_____________________________________________________________________________
00737 RooSimWSTool::BuildConfig::BuildConfig(const char* pdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
00738                                           const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
00739 {
00740   // Construct build configuration from single prototype 'pdfName' and list of arguments
00741   // that can be passed to RooSimWSTool::build() method. This routine parses SplitParam()
00742   // SplitParamConstrained() and Restrict() arguments.
00743 
00744   SplitRule sr(pdfName) ;
00745   sr.configure(arg1,arg2,arg3,arg4,arg5,arg6) ;
00746   internalAddPdf(pdfName,"",sr) ;
00747   _conflProtocol = RooFit::RenameConflictNodes(pdfName) ;
00748 
00749   list<const RooCmdArg*> cmdList ;  
00750   cmdList.push_back(&arg1) ;  cmdList.push_back(&arg2) ;
00751   cmdList.push_back(&arg3) ;  cmdList.push_back(&arg4) ;
00752   cmdList.push_back(&arg5) ;  cmdList.push_back(&arg6) ;
00753 
00754   list<const RooCmdArg*>::iterator iter ;
00755   for (iter=cmdList.begin() ; iter!=cmdList.end() ; ++iter) {
00756     if ((*iter)->opcode()==0) continue ;
00757     string name = (*iter)->opcode() ;
00758     if (name=="Restrict") {
00759       restrictBuild((*iter)->getString(0),(*iter)->getString(1)) ;
00760     }    
00761     if (name=="RenameConflictNodes") {
00762       _conflProtocol = *(*iter) ;
00763     }
00764   }
00765 }
00766 
00767 
00768 //_____________________________________________________________________________
00769 RooSimWSTool::BuildConfig::BuildConfig(const RooArgSet& /*legacyBuildConfig*/) 
00770 {
00771   // Constructor to make BuildConfig from legacy RooSimPdfBuilder configuration
00772   // Empty for now
00773 }
00774 
00775 
00776 //_____________________________________________________________________________
00777 void RooSimWSTool::BuildConfig::internalAddPdf(const char* pdfName, const char* miStateNameList,SplitRule& sr) 
00778 {
00779   // Internal routine to add prototype pdf 'pdfName' with list of associated master states 'miStateNameList
00780   // and split rules 'sr' to configuration
00781 
00782   char buf[4096] ;
00783   strlcpy(buf,miStateNameList,4096) ;
00784   
00785   char* tok = strtok(buf,",") ;
00786   while(tok) {
00787     sr._miStateNameList.push_back(tok) ;
00788     tok = strtok(0,",") ;
00789   }
00790     
00791   _pdfmap[pdfName] = sr ;  
00792 }
00793 
00794 
00795 //_____________________________________________________________________________
00796 void RooSimWSTool::BuildConfig::restrictBuild(const char* catName, const char* stateList) 
00797 {
00798   // Restrict build by only considering state names in stateList for split in category catName
00799   _restr[catName] = stateList ;
00800 }
00801 
00802 
00803 
00804 
00805 //_____________________________________________________________________________
00806 RooSimWSTool::MultiBuildConfig::MultiBuildConfig(const char* masterIndexCat)  
00807 {
00808   // Construct MultiBuildConfig for build configuration with multiple prototype p.d.f.s
00809   // masterIndexCat is the name of the master index category that decides which
00810   // prototype is used.
00811 
00812   _masterCatName = masterIndexCat ;
00813 }
00814 
00815 
00816 
00817 //_____________________________________________________________________________
00818 void RooSimWSTool::MultiBuildConfig::addPdf(const char* miStateList, const char* pdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
00819                                                const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
00820 {
00821   // Add protytpe p.d.f 'pdfName' to MultiBuildConfig associated with master indes states 'miStateList'. This
00822   // method parses the SplitParam() and SplitParamConstrained() arguments
00823 
00824   SplitRule sr(pdfName) ;
00825   sr.configure(arg1,arg2,arg3,arg4,arg5,arg6) ;
00826   internalAddPdf(pdfName,miStateList,sr) ;
00827 }
00828 
00829 
00830 
00831 //_____________________________________________________________________________
00832 void RooSimWSTool::MultiBuildConfig::addPdf(const char* miStateList, const char* pdfName, SplitRule& sr) 
00833 {
00834   // Add protytpe p.d.f 'pdfName' to MultiBuildConfig associated with master indes states 'miStateList'. 
00835 
00836   internalAddPdf(pdfName,miStateList,sr) ;
00837 }
00838 
00839 
00840 
00841 
00842 //_____________________________________________________________________________
00843 RooSimWSTool::ObjSplitRule::~ObjSplitRule()
00844 {
00845   // Destructor
00846 }
00847 
00848 
00849 
00850 
00851 //_____________________________________________________________________________
00852 void RooSimWSTool::ObjBuildConfig::print()
00853 {
00854   // Print details of a validated build configuration
00855 
00856   // --- Dump contents of object build config ---
00857   map<RooAbsPdf*,ObjSplitRule>::iterator ri ;
00858   for (ri = _pdfmap.begin() ; ri != _pdfmap.end() ; ++ri ) {    
00859     cout << "Splitrule for p.d.f " << ri->first->GetName() << " with state list " ;
00860     for (std::list<const RooCatType*>::iterator misi= ri->second._miStateList.begin() ; misi!=ri->second._miStateList.end() ; misi++) {
00861       cout << (*misi)->GetName() << " " ;
00862     }
00863     cout << endl ;
00864 
00865     map<RooAbsArg*,pair<RooArgSet,string> >::iterator csi ;
00866     for (csi = ri->second._paramSplitMap.begin() ; csi != ri->second._paramSplitMap.end() ; ++csi ) {    
00867       if (csi->second.second.length()>0) {
00868         cout << " parameter " << csi->first->GetName() << " is split with constraint in categories " << csi->second.first 
00869              << " with remainder in state " << csi->second.second << endl ;      
00870       } else {
00871         cout << " parameter " << csi->first->GetName() << " is split with constraint in categories " << csi->second.first << endl ;      
00872       }
00873     }        
00874   }
00875 
00876   map<RooAbsCategory*,list<const RooCatType*> >::iterator riter ;
00877   for (riter=_restr.begin() ; riter!=_restr.end() ; ++riter) {
00878     cout << "Restricting build in category " << riter->first->GetName() << " to states " ;
00879     list<const RooCatType*>::iterator i ;
00880     for (i=riter->second.begin() ; i!=riter->second.end() ; i++) {
00881       if (i!=riter->second.begin()) cout << "," ;
00882       cout << (*i)->GetName() ;
00883     }
00884     cout << endl ;
00885   }
00886 
00887 }
00888 
00889 
00890 
00891 
00892 //_____________________________________________________________________________
00893 std::string RooSimWSTool::SimWSIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args) 
00894 {
00895   string tn(typeName) ;
00896   if (tn=="SIMCLONE") {
00897 
00898     // Perform syntax check. Warn about any meta parameters other than $SplitParam, $SplitParamConstrained, $Restrict and $Verbose
00899     for (unsigned int i=1 ; i<args.size() ; i++) {
00900       if (!args[i].find("$SplitParam(")==0 &&
00901           !args[i].find("$SplitParamConstrained(")==0 &&
00902           !args[i].find("$SplitRestrict(")==0 &&
00903           !args[i].find("$Verbose(")==0) {
00904         throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: unknown token %s encountered",args[i].c_str())) ;
00905       }
00906     }
00907 
00908     // Make SplitRule object from $SplitParam and $SplitParamConstrained arguments
00909     RooSimWSTool::SplitRule sr(args[0].c_str()) ;
00910     for (unsigned int i=1 ; i<args.size() ; i++) {
00911       if (args[i].find("$SplitParam(")==0) {
00912         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00913         if (subargs.size()!=2) {
00914           throw string(Form("Incorrect number of arguments in $SplitParam, have %d, expect 2",(Int_t)subargs.size())) ;
00915         }
00916         sr.splitParameter(subargs[0].c_str(),subargs[1].c_str()) ;
00917       } else if (args[i].find("$SplitParamConstrained(")==0) {
00918         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00919         if (subargs.size()!=3) {
00920           throw string(Form("Incorrect number of arguments in $SplitParamConstrained, have %d, expect 3",(Int_t)subargs.size())) ;
00921         }
00922         sr.splitParameterConstrained(subargs[0].c_str(), subargs[1].c_str(), subargs[2].c_str()) ;      
00923       } 
00924     }
00925 
00926     // Make BuildConfig object
00927     RooSimWSTool::BuildConfig bc(args[0].c_str(),sr) ;
00928     for (unsigned int i=1 ; i<args.size() ; i++) {
00929       if (args[i].find("$Restrict(")==0) {
00930         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00931         if (subargs.size()!=2) {
00932           throw string(Form("Incorrect number of arguments in $Restrict, have %d, expect 2",(Int_t)subargs.size())) ;
00933         }
00934         bc.restrictBuild(subargs[0].c_str(),subargs[1].c_str()) ;
00935       }
00936     }
00937 
00938     // Look for verbose flag
00939     Bool_t verbose(kFALSE) ;
00940     for (unsigned int i=1 ; i<args.size() ; i++) {
00941       if (args[i].find("$Verbose(")==0) {
00942         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00943         if (subargs.size()>0) {
00944           verbose = atoi(subargs[0].c_str()) ;
00945         }
00946       }
00947     }
00948 
00949     // Build pdf clone
00950     RooSimWSTool sct(ft.ws()) ;    
00951     RooAbsPdf* pdf = sct.build(instanceName,bc,verbose) ;
00952     if (!pdf) {
00953       throw string(Form("RooSimWSTool::SimWSIFace::create() error in RooSimWSTool::build() for %s",instanceName)) ;
00954     }
00955     
00956     // Import into workspace
00957     ft.ws().import(*pdf,RooFit::Silence()) ;
00958 
00959   } else if (tn=="MSIMCLONE") {
00960 
00961     // First make a multibuild config from the master index cat
00962     RooSimWSTool::MultiBuildConfig mbc(args[0].c_str()) ;
00963 
00964     for (unsigned int i=1 ; i<args.size() ; i++) {
00965       if (args[i].find("$AddPdf(")==0) {
00966         // Process an add-pdf operation
00967         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00968 
00969         // Make SplitRule object from $SplitParam and $SplitParamConstrained arguments
00970         RooSimWSTool::SplitRule sr(subargs[1].c_str()) ;
00971         for (unsigned int j=2 ; j<subargs.size() ; j++) {
00972           if (subargs[j].find("$SplitParam(")==0) {
00973             vector<string> subsubargs = ft.splitFunctionArgs(subargs[j].c_str()) ;
00974             if (subsubargs.size()!=2) {
00975               throw string(Form("Incorrect number of arguments in $SplitParam, have %d, expect 2",(Int_t)subsubargs.size())) ;
00976             }
00977             sr.splitParameter(subsubargs[0].c_str(),subsubargs[1].c_str()) ;
00978           } else if (subargs[j].find("$SplitParamConstrained(")==0) {
00979             vector<string> subsubargs = ft.splitFunctionArgs(subargs[j].c_str()) ;
00980             if (subsubargs.size()!=3) {
00981               throw string(Form("Incorrect number of arguments in $SplitParamConstrained, have %d, expect 3",(Int_t)subsubargs.size())) ;
00982             }
00983             sr.splitParameterConstrained(subsubargs[0].c_str(), subsubargs[1].c_str(), subsubargs[2].c_str()) ; 
00984           } 
00985         }     
00986         mbc.addPdf(subargs[0].c_str(),subargs[1].c_str(),sr) ;
00987 
00988       } else if (args[i].find("$Restrict(")==0) {
00989         
00990         // Process a restrict operation         
00991         vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
00992         if (subargs.size()!=2) {
00993           throw string(Form("Incorrect number of arguments in $Restrict, have %d, expect 2",(Int_t)subargs.size())) ;
00994         }
00995         mbc.restrictBuild(subargs[0].c_str(),subargs[1].c_str()) ;
00996         
00997       } else {
00998         throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: unknown token in MSIMCLONE: %s",args[i].c_str())) ;
00999       }
01000     }    
01001 
01002     // Build pdf clone
01003     RooSimWSTool sct(ft.ws()) ;    
01004     RooAbsPdf* pdf = sct.build(instanceName,mbc,kFALSE) ;
01005     if (!pdf) {
01006       throw string(Form("RooSimWSTool::SimWSIFace::create() error in RooSimWSTool::build() for %s",instanceName)) ;
01007     }
01008     
01009     // Import into workspace
01010     ft.ws().import(*pdf,RooFit::Silence()) ;
01011 
01012     
01013   } else {
01014     throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: Unknown meta-type %s requested",typeName)) ;
01015   }
01016   
01017   return string(instanceName) ;
01018 }

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