#include "RooFit.h"
#include "RooSimWSTool.h"
#include "RooMsgService.h"
#include "RooCategory.h"
#include "RooRealVar.h"
#include "RooAbsPdf.h"
#include "RooStringVar.h"
#include "RooSuperCategory.h"
#include "RooCatType.h"
#include "RooCustomizer.h"
#include "RooMultiCategory.h"
#include "RooSimultaneous.h"
#include "RooGlobalFunc.h"
#include "RooFracRemainder.h"
#include "RooFactoryWSTool.h"
ClassImp(RooSimWSTool)
ClassImp(RooSimWSTool::BuildConfig)
ClassImp(RooSimWSTool::MultiBuildConfig)
ClassImp(RooSimWSTool::SplitRule)
ClassImp(RooSimWSTool::ObjBuildConfig)
ClassImp(RooSimWSTool::ObjSplitRule)
;
using namespace std ;
static Int_t init();
static Int_t dummy = init() ;
static Int_t init()
{
RooFactoryWSTool::IFace* iface = new RooSimWSTool::SimWSIFace ;
RooFactoryWSTool::registerSpecial("SIMCLONE",iface) ;
RooFactoryWSTool::registerSpecial("MSIMCLONE",iface) ;
(void) dummy;
return 0 ;
}
RooSimWSTool::RooSimWSTool(RooWorkspace& ws) : _ws(&ws)
{
}
RooSimWSTool::~RooSimWSTool()
{
}
RooSimultaneous* RooSimWSTool::build(const char* simPdfName, const char* protoPdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
{
BuildConfig bc(protoPdfName,arg1,arg2,arg3,arg4,arg5,arg6) ;
return build(simPdfName,bc) ;
}
RooSimultaneous* RooSimWSTool::build(const char* simPdfName,BuildConfig& bc, Bool_t verbose)
{
ObjBuildConfig* obc = validateConfig(bc) ;
if (!obc) return 0 ;
if (verbose) {
obc->print() ;
}
RooSimultaneous* ret = executeBuild(simPdfName,*obc,verbose) ;
delete obc ;
return ret ;
}
RooSimWSTool::ObjBuildConfig* RooSimWSTool::validateConfig(BuildConfig& bc)
{
ObjBuildConfig* obc = new ObjBuildConfig ;
if (bc._masterCatName.length()>0) {
obc->_masterCat = _ws->cat(bc._masterCatName.c_str()) ;
if (!obc->_masterCat) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName()
<< " does not contain a category named " << bc._masterCatName
<< " that was designated as master index category in the build configuration" << endl ;
delete obc ;
return 0 ;
}
} else {
obc->_masterCat = 0 ;
}
map<string,SplitRule>::iterator pdfiter ;
for (pdfiter = bc._pdfmap.begin() ; pdfiter != bc._pdfmap.end() ; ++pdfiter) {
RooAbsPdf* pdf = _ws->pdf(pdfiter->second.GetName()) ;
if (!pdf) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName()
<< " does not contain a pdf named " << pdfiter->second.GetName() << endl ;
delete obc ;
return 0 ;
}
ObjSplitRule osr ;
SplitRule& sr = pdfiter->second ;
map<string, pair<list<string>,string> >::iterator pariter ;
for (pariter=sr._paramSplitMap.begin() ; pariter!=sr._paramSplitMap.end() ; ++pariter) {
RooAbsArg* farg = _ws->fundArg(pariter->first.c_str()) ;
if (!farg) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName()
<< " does not contain a variable named " << pariter->first.c_str()
<< " as specified in splitting rule of parameter " << pariter->first << " of p.d.f " << pdf << endl ;
delete obc ;
return 0 ;
}
if (!pdf->dependsOn(*farg)) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: specified parameter " << pariter->first
<< " in split is not function of p.d.f " << pdf->GetName() << endl ;
delete obc ;
return 0 ;
}
RooArgSet splitCatSet ;
list<string>::iterator catiter ;
for (catiter = pariter->second.first.begin() ; catiter!=pariter->second.first.end() ; ++catiter) {
RooAbsCategory* cat = _ws->catfunc(catiter->c_str()) ;
if (!cat) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName()
<< " does not contain a category named " << catiter->c_str()
<< " as specified in splitting rule of parameter " << pariter->first << " of p.d.f " << pdf << endl ;
delete obc ;
return 0 ;
}
splitCatSet.add(*cat) ;
}
TIterator* iter = splitCatSet.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
RooArgSet tmp(splitCatSet) ;
tmp.remove(*arg) ;
if (arg->dependsOnValue(tmp)) {
coutE(InputArguments) << "RooSimWSTool::build(" << GetName() << ") ERROR: Ill defined split: splitting category function " << arg->GetName()
<< " used in composite split " << splitCatSet << " of parameter " << farg->GetName() << " of pdf " << pdf->GetName()
<< " depends on one or more of the other splitting categories in the composite split" << endl ;
delete obc ;
delete iter ;
return 0 ;
}
}
delete iter ;
if (pariter->second.second.size()>0) {
if (!dynamic_cast<RooAbsReal*>(farg)) {
coutE(InputArguments) << "RooSimWSTool::build(" << GetName() << ") ERROR: Constrained split specified in non real-valued parameter " << farg->GetName() << endl ;
delete obc ;
return 0 ;
}
}
osr._paramSplitMap[farg].first.add(splitCatSet) ;
osr._paramSplitMap[farg].second = pariter->second.second ;
if (obc->_masterCat) {
list<string>::iterator misi ;
for (misi=sr._miStateNameList.begin() ; misi!=sr._miStateNameList.end() ; ++misi) {
const RooCatType* ctype = obc->_masterCat->lookupType(misi->c_str(),kFALSE) ;
if (ctype==0) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: master index category " << obc->_masterCat->GetName()
<< " does not have a state named " << *misi << " which was specified as state associated with p.d.f "
<< sr.GetName() << endl ;
delete obc ;
return 0 ;
}
osr._miStateList.push_back(ctype) ;
}
}
obc->_usedSplitCats.add(splitCatSet,kTRUE) ;
}
if (sr._paramSplitMap.size()==0) {
if (obc->_masterCat) {
list<string>::iterator misi ;
for (misi=sr._miStateNameList.begin() ; misi!=sr._miStateNameList.end() ; ++misi) {
const RooCatType* ctype = obc->_masterCat->lookupType(misi->c_str(),kFALSE) ;
if (ctype==0) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: master index category " << obc->_masterCat->GetName()
<< " does not have a state named " << *misi << " which was specified as state associated with p.d.f "
<< sr.GetName() << endl ;
delete obc ;
return 0 ;
}
osr._miStateList.push_back(ctype) ;
}
}
}
obc->_pdfmap[pdf] = osr ;
}
map<string,string>::iterator riter ;
for (riter=bc._restr.begin() ; riter!=bc._restr.end() ; ++riter) {
RooCategory* cat = _ws->cat(riter->first.c_str()) ;
if (!cat) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: associated workspace " << _ws->GetName()
<< " does not contain a category named " << riter->first
<< " for which build was requested to be restricted to states " << riter->second << endl ;
delete obc ;
return 0 ;
}
char buf[4096] ;
list<const RooCatType*> rlist ;
strlcpy(buf,riter->second.c_str(),4096) ;
char* tok = strtok(buf,"{,}") ;
while(tok) {
const RooCatType* ctype = cat->lookupType(tok,kFALSE) ;
if (!ctype) {
coutE(ObjectHandling) << "RooSimWSTool::build(" << GetName() << ") ERROR: restricted build category " << cat->GetName()
<< " does not have state " << tok << " as specified in restriction list" << endl ;
delete obc ;
return 0 ;
}
rlist.push_back(ctype) ;
tok = strtok(0,"{,}") ;
}
obc->_restr[cat] = rlist ;
}
return obc ;
}
RooSimultaneous* RooSimWSTool::executeBuild(const char* simPdfName, ObjBuildConfig& obc, Bool_t verbose)
{
RooArgSet cleanupList ;
RooAbsCategoryLValue* physCat = obc._masterCat ;
RooArgSet physModelSet ;
map<string,RooAbsPdf*> stateMap ;
map<RooAbsPdf*,ObjSplitRule>::iterator physIter = obc._pdfmap.begin() ;
while(physIter!=obc._pdfmap.end()) {
RooAbsPdf* physModel = physIter->first ;
physModelSet.add(*physModel,kTRUE) ;
list<const RooCatType*>::iterator stiter ;
for (stiter=physIter->second._miStateList.begin() ; stiter!=physIter->second._miStateList.end() ; ++stiter) {
stateMap[(*stiter)->GetName()] = physModel ;
}
++physIter ;
}
if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: list of prototype pdfs " << physModelSet << endl ;
RooArgSet splitCatSet(obc._usedSplitCats) ;
if (physCat) splitCatSet.add(*physCat) ;
RooArgSet splitCatSetFund ;
TIterator* scsiter = splitCatSet.createIterator() ;
RooAbsCategory* scat ;
while((scat=(RooAbsCategory*)scsiter->Next())) {
if (scat->isFundamental()) {
splitCatSetFund.add(*scat) ;
} else {
RooArgSet* scatvars = scat->getVariables() ;
splitCatSetFund.add(*scatvars) ;
delete scatvars ;
}
}
delete scsiter ;
RooAbsCategoryLValue* masterSplitCat ;
if (splitCatSetFund.getSize()>1) {
masterSplitCat = new RooSuperCategory("masterSplitCat","Master splitting category",splitCatSetFund) ;
} else {
masterSplitCat = (RooAbsCategoryLValue*) splitCatSetFund.first() ;
}
if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: list of splitting categories " << splitCatSet << endl ;
RooArgSet splitNodeListOwned ;
RooArgSet splitNodeListAll ;
TList* customizerList = new TList ;
TIterator* physMIter = physModelSet.createIterator() ;
RooAbsPdf* physModel ;
while((physModel=(RooAbsPdf*)physMIter->Next())) {
if (verbose) coutI(ObjectHandling) << "RooSimPdfBuilder::executeBuild: processing prototype pdf " << physModel->GetName() << endl ;
RooCustomizer* physCustomizer = new RooCustomizer(*physModel,*masterSplitCat,splitNodeListOwned,&splitNodeListAll) ;
customizerList->Add(physCustomizer) ;
map<RooAbsArg*, pair<RooArgSet,string> >::iterator splitIter ;
for (splitIter = obc._pdfmap[physModel]._paramSplitMap.begin() ; splitIter != obc._pdfmap[physModel]._paramSplitMap.end() ; ++splitIter) {
RooArgSet& splitCatSetTmp = splitIter->second.first ;
string splitName = makeSplitName(splitCatSetTmp) ;
RooAbsCategory* splitCat = _ws->catfunc(splitName.c_str()) ;
if (!splitCat) {
splitCat = new RooMultiCategory(splitName.c_str(),splitName.c_str(),splitCatSetTmp) ;
cleanupList.addOwned(*splitCat) ;
_ws->import(*splitCat,RooFit::Silence(!verbose)) ;
}
if(splitIter->second.second.size()>0) {
if (!splitCat->lookupType(splitIter->second.second.c_str())) {
coutE(InputArguments) << "RooSimWSTool::executeBuild(" << GetName() << ") ERROR: name of remainder state for constrained split, '"
<< splitIter->second.second << "' , does not match any state name of (composite) split category " << splitCat->GetName() << endl ;
return 0 ;
}
RooArgSet fracLeafList ;
TIterator* sctiter = splitCat->typeIterator() ;
RooCatType* type ;
while((type=(RooCatType*)sctiter->Next())) {
if (splitIter->second.second == type->GetName()) continue ;
TString splitLeafName(splitIter->first->GetName()) ;
splitLeafName.Append("_") ;
splitLeafName.Append(type->GetName()) ;
RooAbsArg* splitLeaf = _ws->fundArg(splitLeafName) ;
if (!splitLeaf) {
splitLeaf = (RooAbsArg*) splitIter->first->clone(splitLeafName) ;
_ws->import(*splitLeaf,RooFit::Silence(!verbose)) ;
}
fracLeafList.add(*splitLeaf) ;
}
delete sctiter ;
RooFracRemainder* fracRem = new RooFracRemainder(Form("%s_%s",splitIter->first->GetName(),splitIter->second.second.c_str()),"Remainder fraction",fracLeafList) ;
cleanupList.addOwned(*fracRem) ;
_ws->import(*fracRem) ;
}
physCustomizer->splitArgs(*splitIter->first,*splitCat) ;
}
}
delete physMIter ;
splitNodeListAll.add(_ws->components()) ;
if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: configured customizers for all prototype pdfs" << endl ;
RooArgSet fitCatList ;
if (physCat) fitCatList.add(*physCat) ;
scsiter = splitCatSet.createIterator() ;
while((scat=(RooAbsCategory*)scsiter->Next())) {
if (scat->isFundamental()) {
fitCatList.add(*scat) ;
} else {
RooArgSet* scatvars = scat->getVariables() ;
fitCatList.add(*scatvars) ;
delete scatvars ;
}
}
delete scsiter ;
TIterator* fclIter = fitCatList.createIterator() ;
string mcatname = string(simPdfName) + "_index" ;
RooAbsCategoryLValue* fitCat = 0 ;
if (fitCatList.getSize()>1) {
fitCat = new RooSuperCategory(mcatname.c_str(),mcatname.c_str(),fitCatList) ;
cleanupList.addOwned(*fitCat) ;
} else {
fitCat = (RooAbsCategoryLValue*) fitCatList.first() ;
}
RooSimultaneous* simPdf = new RooSimultaneous(simPdfName,simPdfName,*fitCat) ;
cleanupList.addOwned(*simPdf) ;
TIterator* fcIter = fitCat->typeIterator() ;
RooCatType* fcState ;
while((fcState=(RooCatType*)fcIter->Next())) {
fitCat->setLabel(fcState->GetName()) ;
fclIter->Reset() ;
RooAbsCategory* splitCat ;
Bool_t select(kFALSE) ;
if (obc._restr.size()>0) {
while((splitCat=(RooAbsCategory*)fclIter->Next())) {
list<const RooCatType*> slist = obc._restr[splitCat] ;
if (slist.size()==0) {
continue ;
}
list<const RooCatType*>::iterator sli ;
for (sli=slist.begin() ; sli!=slist.end() ; ++sli) {
if (string(splitCat->getLabel())==(*sli)->GetName()) {
select=kTRUE ;
}
}
}
if (!select) continue ;
} else {
select = kTRUE ;
}
RooCustomizer* physCustomizer ;
if (physCat) {
RooAbsPdf* pdf = stateMap[physCat->getLabel()] ;
if (pdf==0) {
continue ;
}
physCustomizer = (RooCustomizer*) customizerList->FindObject(pdf->GetName());
} else {
physCustomizer = (RooCustomizer*) customizerList->First() ;
}
if (verbose) coutI(ObjectHandling) << "RooSimWSTool::executeBuild: Customizing prototype pdf " << physCustomizer->GetName()
<< " for mode " << fcState->GetName() << endl ;
RooAbsPdf* fcPdf = (RooAbsPdf*) physCustomizer->build(masterSplitCat->getLabel(),kFALSE) ;
simPdf->addPdf(*fcPdf,fcState->GetName()) ;
}
delete fcIter ;
_ws->import(*simPdf,obc._conflProtocol,RooFit::Silence(!verbose)) ;
customizerList->Delete() ;
delete customizerList ;
delete fclIter ;
return (RooSimultaneous*) _ws->pdf(simPdf->GetName()) ;
}
std::string RooSimWSTool::makeSplitName(const RooArgSet& splitCatSet)
{
string name ;
TIterator* iter = splitCatSet.createIterator() ;
RooAbsArg* arg ;
Bool_t first=kTRUE ;
while((arg=(RooAbsArg*)iter->Next())) {
if (first) {
first=kFALSE;
} else {
name += "," ;
}
name += arg->GetName() ;
}
delete iter ;
return name ;
}
void RooSimWSTool::SplitRule::splitParameter(const char* paramNameList, const char* categoryNameList)
{
char paramBuf[4096] ;
char catBuf[4096] ;
strlcpy(paramBuf,paramNameList,4096) ;
strlcpy(catBuf,categoryNameList,4096) ;
list<string> catList ;
char* cat = strtok(catBuf,"{,}") ;
while(cat) {
catList.push_back(cat) ;
cat = strtok(0,"{,}") ;
}
char* param = strtok(paramBuf,"{,}") ;
while(param) {
_paramSplitMap[param] = pair<list<string>,string>(catList,"") ;
param = strtok(0,"{,}") ;
}
}
void RooSimWSTool::SplitRule::splitParameterConstrained(const char* paramNameList, const char* categoryNameList, const char* remainderStateName)
{
char paramBuf[4096] ;
char catBuf[4096] ;
strlcpy(paramBuf,paramNameList,4096) ;
strlcpy(catBuf,categoryNameList,4096) ;
list<string> catList ;
char* cat = strtok(catBuf,"{,}") ;
while(cat) {
catList.push_back(cat) ;
cat = strtok(0,"{,}") ;
}
char* param = strtok(paramBuf,"{,}") ;
while(param) {
_paramSplitMap[param] = pair<list<string>,string>(catList,remainderStateName) ;
param = strtok(0,"{,}") ;
}
}
void RooSimWSTool::SplitRule::configure(const RooCmdArg& arg1,const RooCmdArg& arg2,const RooCmdArg& arg3,
const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
{
list<const RooCmdArg*> cmdList ;
cmdList.push_back(&arg1) ; cmdList.push_back(&arg2) ;
cmdList.push_back(&arg3) ; cmdList.push_back(&arg4) ;
cmdList.push_back(&arg5) ; cmdList.push_back(&arg6) ;
list<const RooCmdArg*>::iterator iter ;
for (iter=cmdList.begin() ; iter!=cmdList.end() ; ++iter) {
if ((*iter)->opcode()==0) continue ;
string name = (*iter)->opcode() ;
if (name=="SplitParam") {
splitParameter((*iter)->getString(0),(*iter)->getString(1)) ;
} else if (name=="SplitParamConstrained") {
splitParameterConstrained((*iter)->getString(0),(*iter)->getString(1),(*iter)->getString(2)) ;
}
}
}
RooSimWSTool::BuildConfig::BuildConfig(const char* pdfName, SplitRule& sr)
{
internalAddPdf(pdfName,"",sr) ;
}
RooSimWSTool::BuildConfig::BuildConfig(const char* pdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
{
SplitRule sr(pdfName) ;
sr.configure(arg1,arg2,arg3,arg4,arg5,arg6) ;
internalAddPdf(pdfName,"",sr) ;
_conflProtocol = RooFit::RenameConflictNodes(pdfName) ;
list<const RooCmdArg*> cmdList ;
cmdList.push_back(&arg1) ; cmdList.push_back(&arg2) ;
cmdList.push_back(&arg3) ; cmdList.push_back(&arg4) ;
cmdList.push_back(&arg5) ; cmdList.push_back(&arg6) ;
list<const RooCmdArg*>::iterator iter ;
for (iter=cmdList.begin() ; iter!=cmdList.end() ; ++iter) {
if ((*iter)->opcode()==0) continue ;
string name = (*iter)->opcode() ;
if (name=="Restrict") {
restrictBuild((*iter)->getString(0),(*iter)->getString(1)) ;
}
if (name=="RenameConflictNodes") {
_conflProtocol = *(*iter) ;
}
}
}
RooSimWSTool::BuildConfig::BuildConfig(const RooArgSet& )
{
}
void RooSimWSTool::BuildConfig::internalAddPdf(const char* pdfName, const char* miStateNameList,SplitRule& sr)
{
char buf[4096] ;
strlcpy(buf,miStateNameList,4096) ;
char* tok = strtok(buf,",") ;
while(tok) {
sr._miStateNameList.push_back(tok) ;
tok = strtok(0,",") ;
}
_pdfmap[pdfName] = sr ;
}
void RooSimWSTool::BuildConfig::restrictBuild(const char* catName, const char* stateList)
{
_restr[catName] = stateList ;
}
RooSimWSTool::MultiBuildConfig::MultiBuildConfig(const char* masterIndexCat)
{
_masterCatName = masterIndexCat ;
}
void RooSimWSTool::MultiBuildConfig::addPdf(const char* miStateList, const char* pdfName, const RooCmdArg& arg1,const RooCmdArg& arg2,
const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6)
{
SplitRule sr(pdfName) ;
sr.configure(arg1,arg2,arg3,arg4,arg5,arg6) ;
internalAddPdf(pdfName,miStateList,sr) ;
}
void RooSimWSTool::MultiBuildConfig::addPdf(const char* miStateList, const char* pdfName, SplitRule& sr)
{
internalAddPdf(pdfName,miStateList,sr) ;
}
RooSimWSTool::ObjSplitRule::~ObjSplitRule()
{
}
void RooSimWSTool::ObjBuildConfig::print()
{
map<RooAbsPdf*,ObjSplitRule>::iterator ri ;
for (ri = _pdfmap.begin() ; ri != _pdfmap.end() ; ++ri ) {
cout << "Splitrule for p.d.f " << ri->first->GetName() << " with state list " ;
for (std::list<const RooCatType*>::iterator misi= ri->second._miStateList.begin() ; misi!=ri->second._miStateList.end() ; misi++) {
cout << (*misi)->GetName() << " " ;
}
cout << endl ;
map<RooAbsArg*,pair<RooArgSet,string> >::iterator csi ;
for (csi = ri->second._paramSplitMap.begin() ; csi != ri->second._paramSplitMap.end() ; ++csi ) {
if (csi->second.second.length()>0) {
cout << " parameter " << csi->first->GetName() << " is split with constraint in categories " << csi->second.first
<< " with remainder in state " << csi->second.second << endl ;
} else {
cout << " parameter " << csi->first->GetName() << " is split with constraint in categories " << csi->second.first << endl ;
}
}
}
map<RooAbsCategory*,list<const RooCatType*> >::iterator riter ;
for (riter=_restr.begin() ; riter!=_restr.end() ; ++riter) {
cout << "Restricting build in category " << riter->first->GetName() << " to states " ;
list<const RooCatType*>::iterator i ;
for (i=riter->second.begin() ; i!=riter->second.end() ; i++) {
if (i!=riter->second.begin()) cout << "," ;
cout << (*i)->GetName() ;
}
cout << endl ;
}
}
std::string RooSimWSTool::SimWSIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args)
{
string tn(typeName) ;
if (tn=="SIMCLONE") {
for (unsigned int i=1 ; i<args.size() ; i++) {
if (args[i].find("$SplitParam(")!=0 &&
args[i].find("$SplitParamConstrained(")!=0 &&
args[i].find("$SplitRestrict(")!=0 &&
args[i].find("$Verbose(")!=0) {
throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: unknown token %s encountered",args[i].c_str())) ;
}
}
RooSimWSTool::SplitRule sr(args[0].c_str()) ;
for (unsigned int i=1 ; i<args.size() ; i++) {
if (args[i].find("$SplitParam(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
if (subargs.size()!=2) {
throw string(Form("Incorrect number of arguments in $SplitParam, have %d, expect 2",(Int_t)subargs.size())) ;
}
sr.splitParameter(subargs[0].c_str(),subargs[1].c_str()) ;
} else if (args[i].find("$SplitParamConstrained(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
if (subargs.size()!=3) {
throw string(Form("Incorrect number of arguments in $SplitParamConstrained, have %d, expect 3",(Int_t)subargs.size())) ;
}
sr.splitParameterConstrained(subargs[0].c_str(), subargs[1].c_str(), subargs[2].c_str()) ;
}
}
RooSimWSTool::BuildConfig bc(args[0].c_str(),sr) ;
for (unsigned int i=1 ; i<args.size() ; i++) {
if (args[i].find("$Restrict(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
if (subargs.size()!=2) {
throw string(Form("Incorrect number of arguments in $Restrict, have %d, expect 2",(Int_t)subargs.size())) ;
}
bc.restrictBuild(subargs[0].c_str(),subargs[1].c_str()) ;
}
}
Bool_t verbose(kFALSE) ;
for (unsigned int i=1 ; i<args.size() ; i++) {
if (args[i].find("$Verbose(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
if (subargs.size()>0) {
verbose = atoi(subargs[0].c_str()) ;
}
}
}
RooSimWSTool sct(ft.ws()) ;
RooAbsPdf* pdf = sct.build(instanceName,bc,verbose) ;
if (!pdf) {
throw string(Form("RooSimWSTool::SimWSIFace::create() error in RooSimWSTool::build() for %s",instanceName)) ;
}
ft.ws().import(*pdf,RooFit::Silence()) ;
} else if (tn=="MSIMCLONE") {
RooSimWSTool::MultiBuildConfig mbc(args[0].c_str()) ;
for (unsigned int i=1 ; i<args.size() ; i++) {
if (args[i].find("$AddPdf(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
RooSimWSTool::SplitRule sr(subargs[1].c_str()) ;
for (unsigned int j=2 ; j<subargs.size() ; j++) {
if (subargs[j].find("$SplitParam(")==0) {
vector<string> subsubargs = ft.splitFunctionArgs(subargs[j].c_str()) ;
if (subsubargs.size()!=2) {
throw string(Form("Incorrect number of arguments in $SplitParam, have %d, expect 2",(Int_t)subsubargs.size())) ;
}
sr.splitParameter(subsubargs[0].c_str(),subsubargs[1].c_str()) ;
} else if (subargs[j].find("$SplitParamConstrained(")==0) {
vector<string> subsubargs = ft.splitFunctionArgs(subargs[j].c_str()) ;
if (subsubargs.size()!=3) {
throw string(Form("Incorrect number of arguments in $SplitParamConstrained, have %d, expect 3",(Int_t)subsubargs.size())) ;
}
sr.splitParameterConstrained(subsubargs[0].c_str(), subsubargs[1].c_str(), subsubargs[2].c_str()) ;
}
}
mbc.addPdf(subargs[0].c_str(),subargs[1].c_str(),sr) ;
} else if (args[i].find("$Restrict(")==0) {
vector<string> subargs = ft.splitFunctionArgs(args[i].c_str()) ;
if (subargs.size()!=2) {
throw string(Form("Incorrect number of arguments in $Restrict, have %d, expect 2",(Int_t)subargs.size())) ;
}
mbc.restrictBuild(subargs[0].c_str(),subargs[1].c_str()) ;
} else {
throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: unknown token in MSIMCLONE: %s",args[i].c_str())) ;
}
}
RooSimWSTool sct(ft.ws()) ;
RooAbsPdf* pdf = sct.build(instanceName,mbc,kFALSE) ;
if (!pdf) {
throw string(Form("RooSimWSTool::SimWSIFace::create() error in RooSimWSTool::build() for %s",instanceName)) ;
}
ft.ws().import(*pdf,RooFit::Silence()) ;
} else {
throw string(Form("RooSimWSTool::SimWSIFace::create() ERROR: Unknown meta-type %s requested",typeName)) ;
}
return string(instanceName) ;
}