RooFactoryWSTool.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooFactoryWSTool.cxx 37172 2010-12-02 08:44:43Z 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 // BEGIN_HTML
00020 // RooFactoryWSTool is a clase like TTree::MakeClass() that generates
00021 // skeleton code for RooAbsPdf and RooAbsReal functions given
00022 // a list of input parameter names. The factory can also compile
00023 // the generated code on the fly, and on request also immediate
00024 // instantiate objects.
00025 // END_HTML
00026 //
00027 
00028 #include "RooFit.h"
00029 
00030 #include "RooFactoryWSTool.h"
00031 #include "RooAbsReal.h"
00032 #include "RooAbsCategory.h"
00033 #include "RooArgList.h"
00034 #include "RooRealVar.h"
00035 #include "RooCategory.h"
00036 #include "RooMsgService.h"
00037 #include "RooWorkspace.h"
00038 #include "TInterpreter.h"
00039 #include "TClass.h"
00040 #include "TClassTable.h"
00041 #include "RooAbsPdf.h"
00042 #include "RooGaussian.h"
00043 #include <fstream>
00044 #include <vector>
00045 #include <string>
00046 #include "RooGlobalFunc.h"
00047 #include "RooDataSet.h"
00048 #include "RooDataHist.h"
00049 #include "RooCintUtils.h"
00050 #include "RooAddPdf.h"
00051 #include "RooProdPdf.h"
00052 #include "RooSimultaneous.h"
00053 #include "RooFFTConvPdf.h"
00054 #include "RooNumConvPdf.h"
00055 #include "RooResolutionModel.h"
00056 #include "RooProduct.h"
00057 #include "RooAddition.h"
00058 #include "RooChi2Var.h"
00059 #include "RooNLLVar.h"
00060 #include "RooRealSumPdf.h"
00061 #include "RooConstVar.h"
00062 #include "RooDerivative.h"
00063 #include "TROOT.h"
00064 
00065 using namespace RooFit ;
00066 using namespace std ;
00067 
00068 ClassImp(RooFactoryWSTool) 
00069 ;
00070 
00071 RooFactoryWSTool* RooFactoryWSTool::_of = 0 ;
00072 map<string,RooFactoryWSTool::IFace*>* RooFactoryWSTool::_hooks=0 ;
00073 
00074 static Int_t init()
00075 {
00076   RooFactoryWSTool::IFace* iface = new RooFactoryWSTool::SpecialsIFace ;
00077 
00078   // Operator p.d.f.s
00079   RooFactoryWSTool::registerSpecial("SUM",iface) ;
00080   RooFactoryWSTool::registerSpecial("RSUM",iface) ;
00081   RooFactoryWSTool::registerSpecial("ASUM",iface) ;
00082   RooFactoryWSTool::registerSpecial("PROD",iface) ;
00083   RooFactoryWSTool::registerSpecial("SIMUL",iface) ;
00084   RooFactoryWSTool::registerSpecial("EXPR",iface) ;
00085   RooFactoryWSTool::registerSpecial("FCONV",iface) ;
00086   RooFactoryWSTool::registerSpecial("NCONV",iface) ;
00087 
00088   // Operator functions
00089   RooFactoryWSTool::registerSpecial("sum",iface) ;
00090   RooFactoryWSTool::registerSpecial("prod",iface) ;
00091   RooFactoryWSTool::registerSpecial("expr",iface) ;
00092   RooFactoryWSTool::registerSpecial("nconv",iface) ;
00093 
00094   // Test statistics
00095   RooFactoryWSTool::registerSpecial("nll",iface) ;
00096   RooFactoryWSTool::registerSpecial("chi2",iface) ;
00097   RooFactoryWSTool::registerSpecial("profile",iface) ;
00098 
00099   // Integration and derivation
00100   RooFactoryWSTool::registerSpecial("int",iface) ;
00101   RooFactoryWSTool::registerSpecial("deriv",iface) ;
00102   RooFactoryWSTool::registerSpecial("cdf",iface) ;
00103   RooFactoryWSTool::registerSpecial("PROJ",iface) ;
00104 
00105   // Miscellaneous
00106   RooFactoryWSTool::registerSpecial("dataobs",iface) ;
00107   RooFactoryWSTool::registerSpecial("set",iface) ;
00108 
00109   return 0 ;
00110 }
00111 static Int_t dummy = init() ;
00112 
00113 
00114 #ifndef _WIN32
00115 #include <strings.h>
00116 #else
00117 
00118 static char *strtok_r(char *s1, const char *s2, char **lasts)
00119 {
00120   char *ret;
00121   
00122   if (s1 == NULL)
00123     s1 = *lasts;
00124   while(*s1 && strchr(s2, *s1))
00125     ++s1;
00126   if(*s1 == '\0')
00127     return NULL;
00128   ret = s1;
00129   while(*s1 && !strchr(s2, *s1))
00130     ++s1;
00131   if(*s1)
00132     *s1++ = '\0';
00133   *lasts = s1;
00134   return ret;
00135 }
00136 
00137 #endif
00138 
00139 
00140 
00141 //_____________________________________________________________________________
00142 RooFactoryWSTool::RooFactoryWSTool(RooWorkspace& inws) : _ws(&inws), _errorCount(0)
00143 {
00144   // Default constructor  
00145 }
00146 
00147 
00148 
00149 //_____________________________________________________________________________
00150 RooFactoryWSTool::~RooFactoryWSTool() 
00151 {
00152   // Destructor
00153 }
00154 
00155 
00156 
00157 
00158 //_____________________________________________________________________________
00159 RooRealVar* RooFactoryWSTool::createVariable(const char* name, Double_t xmin, Double_t xmax)
00160 {
00161   // Low-level factory interface for creating a RooRealVar with a given range and initial value
00162 
00163   // First check if variable already exists
00164   if (_ws->var(name)) {
00165     coutE(ObjectHandling) << "RooFactoryWSTool::createFactory() ERROR: variable with name '" << name << "' already exists" << endl ;
00166     logError() ;
00167     return 0 ;
00168   }
00169 
00170   // Create variable
00171   RooRealVar var(name,name,xmin,xmax) ;
00172 
00173   // Put in workspace
00174   if (_ws->import(var,Silence())) logError() ;
00175 
00176   return _ws->var(name) ;
00177 }
00178 
00179 
00180 
00181 //_____________________________________________________________________________
00182 RooCategory* RooFactoryWSTool::createCategory(const char* name, const char* stateNameList) 
00183 {
00184   // Low-level factory interface for creating a RooCategory with a given list of state names. The State name list
00185   // can be of the form 'name1,name2,name3' or of the form 'name1=id1,name2=id2,name3=id3'
00186 
00187 
00188 
00189   // Create variable
00190   RooCategory cat(name,name) ;
00191 
00192   // Add listed state names
00193   if (stateNameList) {
00194     char *tmp = new char[strlen(stateNameList)+1] ;
00195     strlcpy(tmp,stateNameList,strlen(stateNameList)+1) ;
00196     char* save ;
00197     char* tok = strtok_r(tmp,",",&save) ;
00198     while(tok) {
00199       char* sep = strchr(tok,'=') ;
00200       if (sep) {
00201         *sep = 0 ;
00202         Int_t id = atoi(sep+1) ;
00203         cat.defineType(tok,id) ;
00204         *sep = '=' ;
00205       } else {
00206         cat.defineType(tok) ;
00207       }
00208       tok = strtok_r(0,",",&save) ;
00209     }
00210     delete[] tmp ;
00211   }
00212 
00213   cat.setStringAttribute("factory_tag",Form("%s[%s]",name,stateNameList)) ;
00214 
00215   // Put in workspace
00216   if (_ws->import(cat,Silence())) logError() ;  
00217 
00218   return _ws->cat(name) ;
00219 }
00220 
00221 
00222 
00223 //_____________________________________________________________________________
00224 RooAbsArg* RooFactoryWSTool::createArg(const char* className, const char* objName, const char* varList) 
00225 {
00226   // Low-level factory interface for creating a RooAbsPdf of a given class with a given list of input variables
00227   // The variable list varList should be of the form "a,b,c" where the interpretation of the argument is
00228   // dependent on the p.d.f. Set and List arguments can be passed by substituting a single argument with
00229   // the form (a,b,c), i.e. one can set varList to "x,(a0,a1,a2)" to pass a RooAbsReal and a RooArgSet as arguments.
00230   
00231   // Find class in ROOT class table
00232   TClass* tc = resolveClassName(className) ;
00233   if (!tc) {
00234     coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not found in factory alias table, nor in ROOT class table" << endl ;
00235     logError() ;
00236     return 0 ;
00237   }
00238 
00239   className = tc->GetName() ;
00240 
00241   // Check that class inherits from RooAbsPdf
00242   if (!tc->InheritsFrom(RooAbsArg::Class())) {
00243     coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " does not inherit from RooAbsArg" << endl ;
00244     logError() ;
00245     return 0 ;
00246   }
00247 
00248 
00249   _args.clear() ;
00250   char tmp[1024] ;
00251   strlcpy(tmp,varList,1024) ;
00252   char* p=tmp ;
00253   char* tok=tmp ;
00254   Int_t blevel(0) ;
00255   Bool_t litmode(kFALSE) ;
00256   while(*p) {
00257 
00258     // Keep track of opening and closing brackets
00259     if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
00260     if (*p=='}' || *p==')' || *p==']') blevel-- ;
00261 
00262     // Keep track of string literals
00263     if (*p=='"' || *p=='\'') litmode = !litmode ;
00264     
00265     // If we encounter a comma at zero bracket level
00266     // finalize the current token as a completed argument
00267     // and start the next token
00268     if (!litmode && blevel==0 && ((*p)==',')) {
00269       *p = 0 ;
00270       _args.push_back(tok) ;
00271       tok = p+1 ;
00272     }
00273 
00274     p++ ;
00275   }
00276   _args.push_back(tok) ;
00277 
00278 
00279   // Try CINT interface
00280   pair<list<string>,unsigned int> ca = RooCintUtils::ctorArgs(className,_args.size()+2) ;
00281   if (ca.first.size()==0) {
00282     coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR no suitable constructor found for class " << className << endl ;
00283     logError() ;
00284     return 0 ;
00285   }  
00286 
00287 
00288   // Check if number of provided args is in valid range (add two to accomodate name and title strings)
00289   if (_args.size()+2<ca.second || _args.size()+2>ca.first.size()) {
00290     if (ca.second==ca.first.size()) {
00291       coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid, " << className 
00292                             << " expects " << ca.first.size()-2 << endl ;
00293       logError() ;
00294     } else {
00295       coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR number of arguments provided (" << _args.size() << ") for class is invalid " << className 
00296                             << " expect number between " << ca.second-2 << " and " << ca.first.size()-2 << endl ;
00297       logError() ;
00298     }
00299     return 0 ;
00300   }
00301 
00302   // Now construct CINT constructor spec, start with mandatory name and title args
00303   string cintExpr(Form("new %s(\"%s\",\"%s\"",className,objName,objName)) ;
00304 
00305   // Install argument in static data member to be accessed below through static CINT interface functions  
00306   _of = this ;
00307 
00308   
00309   try {
00310     Int_t i(0) ;
00311     list<string>::iterator ti = ca.first.begin() ; ti++ ; ti++ ;
00312     for (vector<string>::iterator ai = _args.begin() ; ai != _args.end() ; ai++,ti++,i++) {
00313       if ((*ti)=="RooAbsReal&" || (*ti)=="const RooAbsReal&") {
00314         RooFactoryWSTool::as_FUNC(i) ;
00315         cintExpr += Form(",RooFactoryWSTool::as_FUNC(%d)",i) ;
00316       } else if ((*ti)=="RooAbsArg&" || (*ti)=="const RooAbsArg&") {
00317         RooFactoryWSTool::as_ARG(i) ;
00318         cintExpr += Form(",RooFactoryWSTool::as_ARG(%d)",i) ;
00319       } else if ((*ti)=="RooRealVar&" || (*ti)=="const RooRealVar&") {
00320         RooFactoryWSTool::as_VAR(i) ;
00321         cintExpr += Form(",RooFactoryWSTool::as_VAR(%d)",i) ;
00322       } else if ((*ti)=="RooAbsRealLValue&" || (*ti)=="const RooAbsRealLValue&") {
00323         RooFactoryWSTool::as_VARLV(i) ;
00324         cintExpr += Form(",RooFactoryWSTool::as_VARLV(%d)",i) ;
00325       } else if ((*ti)=="RooCategory&" || (*ti)=="const RooCategory&") {
00326         RooFactoryWSTool::as_CAT(i) ;
00327         cintExpr += Form(",RooFactoryWSTool::as_CAT(%d)",i) ;
00328       } else if ((*ti)=="RooAbsCategory&" || (*ti)=="const RooAbsCategory&") {
00329         RooFactoryWSTool::as_CATFUNC(i) ;
00330         cintExpr += Form(",RooFactoryWSTool::as_CATFUNC(%d)",i) ;
00331       } else if ((*ti)=="RooAbsCategoryLValue&" || (*ti)=="const RooAbsCategoryLValue&") {
00332         RooFactoryWSTool::as_CATLV(i) ;
00333         cintExpr += Form(",RooFactoryWSTool::as_CATLV(%d)",i) ;
00334       } else if ((*ti)=="RooAbsPdf&" || (*ti)=="const RooAbsPdf&") {
00335         RooFactoryWSTool::as_PDF(i) ;
00336         cintExpr += Form(",RooFactoryWSTool::as_PDF(%d)",i) ;
00337       } else if ((*ti)=="RooResolutionModel&" || (*ti)=="const RooResolutionModel&") {
00338         RooFactoryWSTool::as_RMODEL(i) ;
00339         cintExpr += Form(",RooFactoryWSTool::as_RMODEL(%d)",i) ;
00340       } else if ((*ti)=="RooAbsData&" || (*ti)=="const RooAbsData&") {
00341         RooFactoryWSTool::as_DATA(i) ;
00342         cintExpr += Form(",RooFactoryWSTool::as_DATA(%d)",i) ;
00343       } else if ((*ti)=="RooDataSet&" || (*ti)=="const RooDataSet&") {
00344         RooFactoryWSTool::as_DSET(i) ;
00345         cintExpr += Form(",RooFactoryWSTool::as_DSET(%d)",i) ;
00346       } else if ((*ti)=="RooDataHist&" || (*ti)=="const RooDataHist&") {
00347         RooFactoryWSTool::as_DHIST(i) ;
00348         cintExpr += Form(",RooFactoryWSTool::as_DHIST(%d)",i) ;
00349       } else if ((*ti)=="const RooArgSet&") {
00350         RooFactoryWSTool::as_SET(i) ;
00351         cintExpr += Form(",RooFactoryWSTool::as_SET(%d)",i) ;
00352       } else if ((*ti)=="const RooArgList&") {
00353         RooFactoryWSTool::as_LIST(i) ;
00354         cintExpr += Form(",RooFactoryWSTool::as_LIST(%d)",i) ;
00355       } else if ((*ti)=="const char*") {
00356         RooFactoryWSTool::as_STRING(i) ;
00357         cintExpr += Form(",RooFactoryWSTool::as_STRING(%d)",i) ;        
00358       } else if ((*ti)=="Int_t" || (*ti)=="int" || (*ti)=="Bool_t" || (*ti)=="bool") {
00359         RooFactoryWSTool::as_INT(i) ;
00360         cintExpr += Form(",RooFactoryWSTool::as_INT(%d)",i) ;   
00361       } else if ((*ti)=="Double_t") {
00362         RooFactoryWSTool::as_DOUBLE(i) ;
00363         cintExpr += Form(",RooFactoryWSTool::as_DOUBLE(%d)",i) ;        
00364       } else if (RooCintUtils::isEnum(ti->c_str())) {             
00365         string qualvalue ;
00366         if (_args[i].find(Form("%s::",className)) != string::npos) {                
00367           qualvalue = _args[i].c_str() ;
00368         } else {        
00369           qualvalue =  Form("%s::%s",className,_args[i].c_str()) ;          
00370         }
00371         if (RooCintUtils::isValidEnumValue(ti->c_str(),qualvalue.c_str())) {
00372           cintExpr += Form(",(%s)%s",ti->c_str(),qualvalue.c_str()) ;
00373         } else {
00374           throw string(Form("Supplied argument %s does not represent a valid state of enum %s",_args[i].c_str(),ti->c_str())) ;
00375           }
00376       } else {
00377         // Check if generic object store has argument of given name and type
00378         TObject& obj = RooFactoryWSTool::as_OBJ(i) ;
00379 
00380         // Strip argument type to bare type (i.e. const X& -> X)
00381         string btype ;
00382         if (ti->find("const ")==0) {
00383           btype = ti->c_str()+6 ;
00384         } else {
00385           btype = *ti ;
00386         }
00387         if (btype.find("&")) {
00388           btype.erase(btype.size()-1,btype.size()) ;
00389         }
00390 
00391         // If btype if a typedef, substitute it by the true type name
00392         btype = RooCintUtils::trueName(btype.c_str()) ;
00393 
00394         if (obj.InheritsFrom(btype.c_str())) {
00395           cintExpr += Form(",(%s&)RooFactoryWSTool::as_OBJ(%d)",ti->c_str(),i) ;
00396         } else {
00397           throw string(Form("Required argument with name %s of type '%s' is not in the workspace",_args[i].c_str(),ti->c_str())) ;
00398         }
00399       }
00400     }
00401     cintExpr += ") ;" ;
00402   } catch (string err) {
00403     coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR constructing " << className << "::" << objName << ": " << err << endl ;
00404     logError() ;
00405     return 0 ;
00406   }
00407   
00408   cxcoutD(ObjectHandling) << "RooFactoryWSTool::createArg() Construct expression is " << cintExpr << endl ;
00409 
00410   // Call CINT to perform constructor call. Catch any error thrown by argument conversion method
00411   RooAbsArg* arg = (RooAbsArg*) gROOT->ProcessLineFast(cintExpr.c_str()) ;
00412 
00413   if (arg) {    
00414     if (string(className)=="RooGenericPdf") {
00415       arg->setStringAttribute("factory_tag",Form("EXPR::%s(%s)",objName,varList)) ;
00416     } else if (string(className)=="RooFormulaVar") {
00417       arg->setStringAttribute("factory_tag",Form("expr::%s(%s)",objName,varList)) ;
00418     } else {
00419       arg->setStringAttribute("factory_tag",Form("%s::%s(%s)",className,objName,varList)) ;
00420     }
00421     if (_ws->import(*arg,Silence())) logError() ;
00422     RooAbsArg* ret = _ws->arg(objName) ;
00423     delete arg ;
00424     return ret ;
00425   } else {
00426     coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR in CINT constructor call to create object" << endl ;
00427     logError() ;
00428     return 0 ;
00429   }
00430 }
00431 
00432 
00433 
00434 //_____________________________________________________________________________
00435 vector<string> RooFactoryWSTool::ctorArgs(const char* /*className*/) 
00436 {
00437   return vector<string>() ;
00438 }
00439 
00440 
00441 
00442 
00443 //_____________________________________________________________________________
00444 RooAddPdf* RooFactoryWSTool::add(const char *objName, const char* specList, Bool_t recursiveCoefs)
00445 {
00446 
00447   // Spec list is of form a*A,b*B,c*C,D [ *d]
00448 
00449   RooArgList pdfList ;
00450   RooArgList coefList ;
00451   RooArgList pdfList2 ;
00452 
00453   try {
00454 
00455     char buf[1024] ;
00456     strlcpy(buf,specList,1024) ;
00457     char* save ;
00458     char* tok = strtok_r(buf,",",&save) ;
00459     while(tok) {
00460       char* star=strchr(tok,'*') ;
00461       if (star) {
00462         *star=0 ;
00463         pdfList.add(asPDF(star+1)) ;
00464         coefList.add(asFUNC(tok)) ;
00465       } else {
00466         pdfList2.add(asPDF(tok)) ;
00467       }
00468       tok = strtok_r(0,",",&save) ;
00469     }
00470     pdfList.add(pdfList2) ;
00471 
00472   } catch (string err) {
00473     coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooAddPdf: " << err << endl ;    
00474     logError() ;
00475     return 0 ;
00476   }
00477   
00478   RooAddPdf* pdf =  new RooAddPdf(objName,objName,pdfList,coefList,recursiveCoefs) ;
00479   pdf->setStringAttribute("factory_tag",Form("SUM::%s(%s)",objName,specList)) ;
00480   if (_ws->import(*pdf,Silence())) logError() ;
00481   return (RooAddPdf*) _ws->pdf(objName) ;
00482 }
00483 
00484 
00485 //_____________________________________________________________________________
00486 RooRealSumPdf* RooFactoryWSTool::amplAdd(const char *objName, const char* specList)
00487 {
00488 
00489   // Spec list is of form a*A,b*B,c*C,D [ *d]
00490 
00491   RooArgList amplList ;
00492   RooArgList coefList ;
00493   RooArgList amplList2 ;
00494 
00495   try {
00496 
00497     char buf[1024] ;
00498     strlcpy(buf,specList,1024) ;
00499     char* save ;
00500     char* tok = strtok_r(buf,",",&save) ;
00501     while(tok) {
00502       char* star=strchr(tok,'*') ;
00503       if (star) {
00504         *star=0 ;
00505         amplList.add(asFUNC(star+1)) ;
00506         coefList.add(asFUNC(tok)) ;
00507       } else {
00508         amplList2.add(asFUNC(tok)) ;
00509       }
00510       tok = strtok_r(0,",",&save) ;
00511     }
00512     amplList.add(amplList2) ;
00513 
00514   } catch (string err) {
00515     coutE(ObjectHandling) << "RooFactoryWSTool::add(" << objName << ") ERROR creating RooRealSumPdf: " << err << endl ;    
00516     logError() ;
00517     return 0 ;
00518   }
00519   
00520   RooRealSumPdf* pdf =  new RooRealSumPdf(objName,objName,amplList,coefList) ;
00521   pdf->setStringAttribute("factory_tag",Form("ASUM::%s(%s)",objName,specList)) ;
00522   if (_ws->import(*pdf,Silence())) logError() ;
00523   return (RooRealSumPdf*) _ws->pdf(objName) ;
00524 }
00525 
00526 
00527 //_____________________________________________________________________________
00528 RooProdPdf* RooFactoryWSTool::prod(const char *objName, const char* pdfList) 
00529 {
00530   _of = this ;
00531 
00532   // Separate conditional and non-conditional p.d.f terms
00533   RooLinkedList cmdList ;
00534   string regPdfList="{" ;
00535   char buf[1024] ;
00536   strlcpy(buf,pdfList,1024) ;
00537   char* save ;
00538   char* tok = strtok_r(buf,",",&save) ;
00539   while(tok) {
00540     char *sep = strchr(tok,'|') ;
00541     if (sep) {
00542       // Conditional term
00543       *sep=0 ;
00544       sep++ ;
00545       
00546       try {
00547         cmdList.Add(Conditional(asSET(tok),asSET(sep),kTRUE).Clone()) ;
00548       } catch (string err) {
00549         coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf Conditional argument: " << err << endl ;
00550         logError() ;
00551         return 0 ;
00552       }
00553       
00554     } else {
00555       // Regular term
00556       if (regPdfList.size()>1) {
00557         regPdfList += "," ;
00558       }
00559       regPdfList += tok ;
00560     }
00561     tok = strtok_r(0,",",&save) ;
00562   }
00563   regPdfList += "}" ;
00564   
00565   RooProdPdf* pdf = 0 ;
00566   try {
00567     pdf = new RooProdPdf(objName,objName,asSET(regPdfList.c_str()),cmdList) ;
00568   } catch (string err) {
00569     coutE(ObjectHandling) << "RooFactoryWSTool::prod(" << objName << ") ERROR creating RooProdPdf input set of regular p.d.f.s: " << err << endl ;
00570     logError() ;
00571     pdf = 0 ;
00572   }
00573   cmdList.Delete() ;
00574   
00575   if (pdf) {
00576     pdf->setStringAttribute("factory_tag",Form("PROD::%s(%s)",objName,pdfList)) ;
00577     if (_ws->import(*pdf,Silence())) logError() ;
00578     delete pdf ;
00579     return (RooProdPdf*) _ws->pdf(objName) ;
00580   } else {
00581     return 0 ;
00582   }
00583 }
00584 
00585 
00586 
00587 //_____________________________________________________________________________
00588 RooSimultaneous* RooFactoryWSTool::simul(const char* objName, const char* indexCat, const char* pdfMap)
00589 {
00590   map<string,RooAbsPdf*> theMap ;
00591   // Add p.d.f. to index state mappings
00592   char buf[1024] ;
00593   strlcpy(buf,pdfMap,1024) ;
00594   char* save ;
00595   char* tok = strtok_r(buf,",",&save) ;
00596   while(tok) {
00597     char* eq = strchr(tok,'=') ;
00598     if (!eq) {
00599       coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName 
00600                             << " expect mapping token of form 'state=pdfName', but found '" << tok << "'" << endl ;
00601       logError() ;
00602       return 0 ;
00603     } else {
00604       *eq = 0 ;
00605 
00606       try {
00607         theMap[tok] = &asPDF(eq+1) ;
00608       } catch ( string err ) {
00609         coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous: " << err << endl ;
00610         logError() ;
00611       }
00612     }
00613     tok = strtok_r(0,",",&save) ;
00614   }
00615 
00616 
00617   // Create simultaneous p.d.f.
00618   RooSimultaneous* pdf(0) ;
00619   try {
00620     pdf = new RooSimultaneous(objName,objName,theMap,asCATLV(indexCat)) ;
00621   } catch (string err) {
00622     coutE(ObjectHandling) << "RooFactoryWSTool::simul(" << objName << ") ERROR creating RooSimultaneous::" << objName << " " << err << endl ;
00623     logError() ;
00624   }
00625 
00626   // Import p.d.f into workspace
00627   pdf->setStringAttribute("factory_tag",Form("SIMUL::%s(%s,%s)",objName,indexCat,pdfMap)) ;
00628   if (_ws->import(*pdf,Silence())) logError() ;
00629   return (RooSimultaneous*) _ws->pdf(objName) ;
00630 }
00631 
00632 
00633 
00634 
00635 //_____________________________________________________________________________
00636 RooAddition* RooFactoryWSTool::addfunc(const char *objName, const char* specList) 
00637 {
00638 
00639   RooArgList sumlist1 ;
00640   RooArgList sumlist2 ;
00641 
00642   try {
00643 
00644     char buf[1024] ;
00645     strlcpy(buf,specList,1024) ;
00646     char* save ;
00647     char* tok = strtok_r(buf,",",&save) ;
00648     while(tok) {
00649       char* star=strchr(tok,'*') ;
00650       if (star) {
00651         *star=0 ;
00652         sumlist2.add(asFUNC(star+1)) ;
00653         sumlist1.add(asFUNC(tok)) ;
00654       } else {
00655         sumlist1.add(asFUNC(tok)) ;
00656       }
00657       tok = strtok_r(0,",",&save) ;
00658     }
00659 
00660   } catch (string err) {
00661     coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: " << err << endl ;
00662     logError() ;
00663     return 0 ;
00664   }
00665 
00666   if (sumlist2.getSize()>0 && (sumlist1.getSize()!=sumlist2.getSize())) {
00667     coutE(ObjectHandling) << "RooFactoryWSTool::addfunc(" << objName << ") ERROR creating RooAddition: syntax error: either all sum terms must be products or none" << endl ;
00668     logError() ;
00669     return 0 ;
00670   }
00671 
00672 
00673   RooAddition* sum ;
00674   if (sumlist2.getSize()>0) {
00675     sum = new RooAddition(objName,objName,sumlist1,sumlist2) ;
00676   } else {
00677     sum = new RooAddition(objName,objName,sumlist1) ;
00678   }
00679 
00680   sum->setStringAttribute("factory_tag",Form("sum::%s(%s)",objName,specList)) ;
00681   if (_ws->import(*sum,Silence())) logError() ;
00682   delete sum ;
00683   return (RooAddition*) _ws->pdf(objName) ;
00684   
00685 }
00686 
00687 
00688 
00689 
00690 //_____________________________________________________________________________
00691 RooProduct* RooFactoryWSTool::prodfunc(const char *objName, const char* pdfList) 
00692 {
00693   return (RooProduct*) createArg("RooProduct",objName,Form("{%s}",pdfList)) ;
00694 }
00695 
00696 
00697 
00698 
00699 
00700 //_____________________________________________________________________________
00701 RooAbsArg* RooFactoryWSTool::process(const char* expr) 
00702 {
00703   // Process high-level object creation syntax
00704   // Accepted forms of syntax are
00705   //
00706   //
00707   // Creating variables
00708   //
00709   // x[-10,10]             -  Create variable x with given range and put it in workspace
00710   // x[3,-10,10]           -  Create variable x with given range and initial value and put it in workspace
00711   // x[3]                  -  Create variable x with given constant value
00712   //
00713   // <numeric literal>     - Numeric literal expressions (0.5, -3 etc..) are converted to a RooConst(<numeric literal>) 
00714   //                         where ever a RooAbsReal or RooAbsArg argument is expected
00715   //
00716   // Creating categories
00717   //
00718   // c[lep,kao,nt1,nt2]    -  Create category c with given state names
00719   // tag[B0=1,B0bar=-1]    -  Create category tag with given state names and index assignments
00720   //
00721   //
00722   // Creating functions and p.d.f.s
00723   //
00724   // MyPdf::g(x,m,s)       - Create p.d.f or function of type MyPdf with name g with argument x,m,s
00725   //                         Interpretation and number of arguments are mapped to the constructor arguments of the class 
00726   //                         (after the name and title).
00727   //
00728   // MyPdf(x,m,s)          - As above, but with an implicitly defined (unique) object name
00729   // 
00730   //
00731   // Creating sets and lists (to be used as inputs above)
00732   //
00733   // {a,b,c}               - Create RooArgSet or RooArgList (as determined by context) from given contents
00734   //
00735   //
00736   //
00737   // Objects that are not created, are assumed to exist in the workspace
00738   // Object creation expressions as shown above can be nested, e.g. one can do
00739   //
00740   //   RooGaussian::g(x[-10,10],m[0],3) 
00741   //
00742   // to create a p.d.f and its variables in one go. This nesting can be applied recursively e.g.
00743   //
00744   //   SUM::model( f[0.5,0,1] * RooGaussian::g( x[-10,10], m[0], 3] ),
00745   //                            RooChebychev::c( x, {a0[0.1],a1[0.2],a2[-0.3]} ))
00746   //
00747   // creates the sum of a Gaussian and a Chebychev and all its variables
00748   //
00749   //
00750   // A seperate series of operator meta-type exists to simplify the construction of composite expressions
00751   // meta-types in all capitals (SUM) create p.d.f.s, meta types in lower case (sum) create
00752   // functions.
00753   //
00754   //
00755   // SUM::name(f1*pdf1,f2*pdf2,pdf3]  -- Create sum p.d.f name with value f1*pdf1+f2*pdf2+(1-f1-f2)*pdf3
00756   // RSUM::name(f1*pdf1,f2*pdf2,pdf3] -- Create recursive sum p.d.f. name with value f1*pdf1 + (1-f1)(f2*pdf2 + (1-f2)pdf3)
00757   // ASUM::name(f1*amp1,f2*amp2,amp3] -- Create sum p.d.f. name with value f1*amp1+f2*amp2+(1-f1-f2)*amp3 where amplX are amplitudes of type RooAbsReal
00758   // sum::name(a1,a2,a3]              -- Create sum function with value a1+a2+a3
00759   // sum::name(a1*b1,a2*b2,a3*b 3]    -- Create sum function with value a1*b1+a2*b2+a3*b3
00760   //
00761   // PROD::name(pdf1,pdf2]            -- Create product of p.d.f with 'name' with given input p.d.fs
00762   // PROD::name(pdf1|x,pdf2]          -- Create product of conditional p.d.f. pdf1 given x and pdf2
00763   // prod::name(a,b,c]                -- Create production function with value a*b*c
00764   //
00765   // SIMUL::name(cat,a=pdf1,b=pdf2]   -- Create simultaneous p.d.f index category cat. Make pdf1 to state a, pdf2 to state b
00766   //
00767   // EXPR::name('expr',var,...]       -- Create an generic p.d.f that interprets the given expression 
00768   // expr::name('expr',var,...]       -- Create an generic function that interprets the given expression 
00769   //
00770   //
00771   // The functionality of high level object creation tools like RooSimWSTool, RooCustomizer and RooClassFactory
00772   // is also interfaced through meta-types in the factory
00773   //
00774   //
00775   // Interface to RooSimWSTool
00776   //
00777   // SIMCLONE::name( modelPdf, $ParamSplit(...), 
00778   //                 $ParamSplitConstrained(...), $Restrict(...) ]            -- Clone-and-customize modelPdf according to ParamSplit and ParamSplitConstrained()
00779   //                                                                             specifications and return a RooSimultaneous p.d.f. of all built clones
00780   //
00781   // MSIMCLONE::name( masterIndex, 
00782   //                  $AddPdf(mstate1, modelPdf1, $ParamSplit(...)), 
00783   //                  $AddPdf(mstate2,modelPdf2),...) ]                       -- Clone-and-customize multiple models (modelPdf1,modelPdf2) according to ParamSplit and 
00784   //                                                                             ParamSplitConstrained() specifications and return a RooSimultaneous p.d.f. of all built clones,
00785   //                                                                             using the specified master index to map prototype p.d.f.s to master states
00786   // Interface to RooCustomizer
00787   //
00788   // EDIT::name( orig, substNode=origNode), ... ]                             -- Create a clone of input object orig, with the specified replacements operations executed
00789   //
00790   //
00791   // Interface to RooClassFactory
00792   //
00793   // CEXPR::name('expr',var,...]       -- Create an custom compiled p.d.f that evaluates the given expression 
00794   // cexpr::name('expr',var,...]       -- Create an custom compiled function that evaluates the given expression 
00795   //
00796   //
00797   // $MetaType(...)        - Meta argument that does not result in construction of an object but is used logically organize 
00798   //                         input arguments in certain operator p.d.f. constructions. The defined meta arguments are context dependent.
00799   //
00800   //                         The only meta argument that is defined globally is $Alias(typeName,aliasName) to  
00801   //                         define aliases for type names. For the definition of meta arguments in operator p.d.f.s
00802   //                         see the definitions below
00803 
00804 
00805   // First perform basic syntax check
00806   if (checkSyntax(expr)) {
00807     return 0 ;
00808   }
00809 
00810   // Allocate work buffer
00811   char* buf = new char[strlen(expr)+1] ;
00812 
00813   // Copy to buffer while absorbing white space and newlines
00814   char* buftmp = buf ;
00815   while(*expr) {
00816     if (!isspace(*expr)) {
00817       *buftmp = *expr ;
00818       buftmp++ ;
00819     }
00820     expr++ ;
00821   }
00822   *buftmp=0 ;
00823 
00824 
00825   // Clear error count and start a transaction in the workspace
00826   clearError() ;
00827   ws().startTransaction() ;
00828 
00829   // Process buffer
00830   string out ;
00831   try {
00832     out = processExpression(buf) ;
00833   } catch (string error) {
00834     coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERROR in parsing: " << error << endl ;
00835     logError() ;
00836   }
00837 
00838   // If there were no errors commit the transaction, cancel it otherwise
00839   if (errorCount()>0) {
00840     coutE(ObjectHandling) << "RooFactoryWSTool::processExpression() ERRORS detected, transaction to workspace aborted, no objects committed" << endl ;
00841     ws().cancelTransaction() ;
00842   } else {
00843     ws().commitTransaction() ;
00844   }
00845 
00846   
00847   // Delete buffer 
00848   delete[] buf ;
00849 
00850   return out.size() ? ws().arg(out.c_str()) : 0 ;
00851 }
00852 
00853 
00854 
00855 
00856 //_____________________________________________________________________________
00857 std::string RooFactoryWSTool::processExpression(const char* token) 
00858 {
00859   // Process a single high-level expression or list of
00860   // expressions. The returned string a the reduced expression where
00861   // all inline object creations have been executed and substituted
00862   // with the name of the created object
00863   //
00864   // e.g. 'RooGaussian::g(x,m,s)' --> 'g'
00865   //      '{x(-10,10),s}          --> '{x,s}'
00866 
00867   // Delegate handling to list processor if token starts with {, otherwise
00868   // call single expression processor
00869   if (string(token).find("$Alias(")==0) {
00870     processAliasExpression(token) ;
00871   }
00872 
00873   if (token[0]=='{') {    
00874     // Process token as list if it starts with '{'
00875     return processListExpression(token) ;
00876   } else {
00877     // Process token as single item otherwise
00878     return processCompositeExpression(token) ;
00879   }
00880 }
00881 
00882 
00883 
00884 //_____________________________________________________________________________
00885 std::string RooFactoryWSTool::processCompositeExpression(const char* token) 
00886 {
00887   // Process a single composite expression 
00888   //
00889   // e.g. 'A=RooGaussian::g[x,m,s]' --> 'A=g'
00890   // e.g. 'f[0,1]*RooGaussian::g[x,m,s]' --> 'f*g'
00891   // e.g. 'RooGaussian::g(x,y,s)|x' --> g|x'
00892   // e.g. '$MetaArg(RooGaussian::g[x,m,s],blah)' --> '$MetaArg(g,blah)'
00893 
00894   // Allocate and fill work buffer
00895   char* buf_base = new char[strlen(token)+1] ;   
00896   char* buf = buf_base ;
00897   strlcpy(buf,token,strlen(token)+1) ;
00898   char* p = buf ;
00899 
00900   list<string> singleExpr ;
00901   list<char> separator ;
00902   Int_t blevel(0) ;
00903   Bool_t litmode(kFALSE) ;
00904   while(*p) {
00905 
00906     // Keep track of opening and closing brackets
00907     if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
00908     if (*p=='}' || *p==')' || *p==']') blevel-- ;
00909     
00910     // Keep track of string literals
00911     if (*p=='"' || *p=='\'') litmode = !litmode ;
00912 
00913     // If we are zero-bracket level and encounter a |, store
00914     // the remainder of the string as suffix and exit loop
00915     if (!litmode && blevel==0 && ( (*p)=='=' || (*p) == '|' || (*p) == '*')) {
00916       separator.push_back(*p) ;
00917       *p=0 ;
00918       singleExpr.push_back(buf) ;
00919       buf = p+1 ;
00920     }
00921     p++ ;
00922   }
00923   if (*buf) {
00924     singleExpr.push_back(buf) ;
00925   }
00926   if (singleExpr.size()==1) {    
00927     string ret = processSingleExpression(token) ;
00928     delete[] buf_base ;
00929     return ret ;
00930   }
00931 
00932   string ret ;
00933   list<char>::iterator ic = separator.begin() ;
00934   for (list<string>::iterator ii = singleExpr.begin() ; ii!=singleExpr.end() ; ii++) {
00935     ret += processSingleExpression(ii->c_str()) ;
00936     if (ic != separator.end()) {
00937       ret += *ic ;
00938       ic++ ;
00939     }
00940   }
00941 
00942   delete[] buf_base ;
00943   return ret ;
00944 }
00945 
00946 
00947 
00948 //_____________________________________________________________________________
00949 std::string RooFactoryWSTool::processSingleExpression(const char* arg) 
00950 {
00951   // Process a single high-level expression. The returned string a the reduced
00952   // expression where all inline object creations have been executed and substituted
00953   // with the name of the created object
00954   //
00955   // e.g. 'RooGaussian::g(x,m,s)' --> 'g'
00956   // e.g. 'x[-10,10]' --> 'x'
00957 
00958   // Handle empty strings here
00959   if (strlen(arg)==0) {
00960     return string("") ;
00961   }
00962 
00963   // Handle string literal case
00964   if (arg[0]=='\'' || arg[0]=='"') {
00965     return string(arg) ;
00966   }
00967 
00968   // Allocate and fill work buffer
00969   char* buf = new char[strlen(arg)+1] ; 
00970   strlcpy(buf,arg,strlen(arg)+1) ;
00971   char* bufptr = buf ;
00972 
00973   string func,prefix ;
00974   vector<string> args ;
00975 
00976   // Process token into arguments
00977   char* save ;
00978   char* tmpx = strtok_r(buf,"([",&save) ;
00979   func = tmpx ? tmpx : "" ;
00980   char* p = strtok_r(0,"",&save) ;
00981   
00982   // Return here if token is fundamental
00983   if (!p) {
00984     delete[] buf ;
00985     return arg ;
00986   }
00987     
00988 
00989   char* tok = p ;
00990   Int_t blevel=0 ;
00991   Bool_t litmode(kFALSE) ;
00992   while(*p) {
00993 
00994     // Keep track of opening and closing brackets
00995     if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
00996     if (*p=='}' || *p==')' || *p==']') blevel-- ;
00997 
00998     // Keep track of string literals
00999     if (*p=='"' || *p=='\'') litmode = !litmode ;
01000 
01001 
01002     // If we encounter a comma at zero bracket level
01003     // finalize the current token as a completed argument
01004     // and start the next token
01005     if (!litmode && blevel==0 && ((*p)==',')) {
01006       *p = 0 ;
01007       args.push_back(tok) ;
01008       tok = p+1 ;
01009     }
01010 
01011     p++ ;
01012   }
01013 
01014   // If the last character was a closing bracket, kill
01015   // it in the buffer
01016   if (p>bufptr && (*(p-1)==')'||*(p-1)==']')) {
01017     *(p-1)=0 ;
01018   }
01019 
01020   // Finalize last token as argument
01021   string tmp = tok ;
01022   
01023   // If there is a suffix left in the work buffer attach it to 
01024   // this argument
01025   p = strtok_r(0,"",&save) ;
01026   if (p) tmp += p ;
01027   args.push_back(tmp) ;
01028 
01029   // Delete the work buffer
01030   delete[] buf ;
01031 
01032   // If function contains :: then call createArg to process this arg, otherwise
01033   // call createVariable
01034   string ret ;
01035 
01036   // Determine type of leading bracket
01037   char lb = ' ' ;  
01038   for(const char* pp=arg ; *pp!=0 ; pp++) {
01039     if (*pp=='(' || *pp=='[' || *pp=='{') {
01040       lb = *pp ;
01041       break ;
01042     }
01043   }
01044 
01045   if (strstr(func.c_str(),"::")) {
01046     if (lb=='(') {
01047       // Create function argument with instance name
01048       ret= processCreateArg(func,args) ;
01049     } else {
01050       coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: Class::Instance must be followed by (...)" << endl ;
01051       logError() ;
01052     }
01053   } else if (func[0]!='$'){    
01054     if (lb=='[') {
01055       // Create variable argument
01056       ret= processCreateVar(func,args) ;
01057     } else if (lb=='(') {
01058 
01059       // Create function argument with autoname
01060       string autoname ;
01061       if (!_autoNamePrefix.empty()) {
01062         // If we're inside a function creation call to a higher level object, use its
01063         // name as base for the autoname
01064         autoname = (Form("%s::%s",func.c_str(),_autoNamePrefix.top().c_str())) ;
01065       } else {
01066         // Otherwise find a free global_%d name
01067         static Int_t globCounter = 0 ;
01068         while(true) {
01069           autoname = Form("gobj%d",globCounter) ;
01070           globCounter++ ;
01071           if (!ws().arg(autoname.c_str())) {
01072             break ;
01073           }
01074         }
01075         autoname = Form("%s::%s",func.c_str(),autoname.c_str()) ;
01076       }
01077       ret= processCreateArg(autoname,args) ;
01078     } else {
01079       coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: expect either Class(...) or Instance[...]" << endl ;
01080       logError() ;
01081     }
01082   } else {
01083     if (lb=='(') {
01084       // Process meta function (compile arguments, but not meta-function itself)
01085       ret= processMetaArg(func,args) ;
01086     } else {
01087       coutE(ObjectHandling) << "RooFactoryWSTool::processSingleExpression(" << arg << "): ERROR: Syntax error: $MetaClass must be followed by (...)" << endl ;
01088       logError() ;
01089     }
01090   }
01091 
01092   // Return reduced token with suffix
01093   return ret ;
01094 }
01095 
01096 
01097 //_____________________________________________________________________________
01098 string RooFactoryWSTool::processListExpression(const char* arg) 
01099 {
01100   // Process a list of high-level expression. The returned string a the reduced
01101   // expression list where all inline object creations have been executed and substituted
01102   // with the name of the created object
01103   //
01104   // E.g.   '{x(-10,10),s}  --> '{x,s}'
01105 
01106   // Allocate and fill work buffer
01107   char* buf = new char[strlen(arg)+1] ;
01108   strlcpy(buf,arg,strlen(arg)+1) ;
01109 
01110   vector<string> args ;
01111 
01112   // Start running pointer at position 1 to skip opening bracket
01113   char* tok = buf+1 ;
01114   char* p = buf+1 ;
01115   
01116   // Processing look
01117   Int_t level(0) ;
01118   while(*p) {
01119 
01120     // Track bracketing level
01121     if (*p=='{' || *p=='(' || *p=='[') level++ ;
01122     if (*p=='}' || *p==')' || *p==']') level-- ;
01123 
01124     
01125     // If we encounter a comma at zero bracket level
01126     // finalize the current token as a completed argument
01127     // and start the next token
01128     if (level==0 && ((*p)==',')) {
01129       *p = 0 ;
01130       args.push_back(tok) ;
01131       tok = p+1 ;
01132     }
01133 
01134     p++ ;
01135   }
01136 
01137   // Finalize token as last argument
01138   if (p>buf && *(p-1)=='}') {
01139     *(p-1)=0 ;
01140   }
01141   args.push_back(tok) ;
01142 
01143   // Delete work buffer
01144   delete[] buf ;
01145 
01146   // Process each argument in list and construct reduced 
01147   // expression to be returned
01148   string ret("{") ;
01149   vector<string>::iterator iter = args.begin() ;
01150   Int_t i(0) ;
01151   while(iter!= args.end()) {
01152     if (strlen(ret.c_str())>1) ret += "," ;
01153     if (!_autoNamePrefix.empty()) {
01154       _autoNamePrefix.push(Form("%s%d",_autoNamePrefix.top().c_str(),i+1)) ;
01155     }
01156     ret += processSingleExpression(iter->c_str()) ;
01157     if (!_autoNamePrefix.empty()) {
01158       _autoNamePrefix.pop() ;
01159     }
01160     iter++ ;
01161     i++ ;
01162   }
01163   ret += "}" ;
01164 
01165   return ret ;
01166 }
01167 
01168 
01169 
01170 //_____________________________________________________________________________
01171 string RooFactoryWSTool::processAliasExpression(const char* token) 
01172 {
01173   // Parse token
01174   vector<string> args = splitFunctionArgs(token) ;
01175   if (args.size()!=2) {
01176     coutE(ObjectHandling) << "RooFactorWSTool::processAliasExpression() ERROR $Alias() takes exactly two arguments, " << args.size() << " args found" << endl ;
01177     logError() ;
01178     return string() ;
01179   }
01180 
01181   // Insert alias in table
01182   _typeAliases[args[1]] = args[0] ;
01183   
01184   return string() ;
01185 }
01186 
01187 
01188 
01189 
01190 //_____________________________________________________________________________
01191 TClass* RooFactoryWSTool::resolveClassName(const char* className) 
01192 {
01193 
01194   // First do recursive alias expansion
01195   while (true) {
01196     map<string,string>::iterator item = _typeAliases.find(className) ;
01197     
01198     // If an alias is found, recurse
01199     if (item != _typeAliases.end()) {
01200       className = item->second.c_str() ;
01201     } else {
01202       break ;
01203     }
01204   }
01205 
01206   // Now find dealiased class in ROOT class table
01207   TClass* tc =  TClass::GetClass(className,kTRUE,kTRUE) ;
01208 
01209   // If its not there, try prefixing with Roo
01210   if (!tc) {
01211     tc = TClass::GetClass(Form("Roo%s",className)) ;
01212     if (!tc) {
01213       coutE(ObjectHandling) << "RooFactoryWSTool::createArg() ERROR class " << className << " not defined in ROOT class table" << endl ;
01214       logError() ;
01215       return 0 ;
01216     } 
01217   }
01218   return tc ;
01219 }
01220 
01221 
01222 
01223 //_____________________________________________________________________________
01224 string RooFactoryWSTool::varTag(string& func, vector<string>& args)
01225 {
01226   string ret ;
01227   ret += func ;
01228   ret += "[" ;
01229   for (vector<string>::iterator iter = args.begin() ; iter!=args.end() ; ++iter) {
01230     if (iter!=args.begin()) {
01231       ret += "," ;
01232     }
01233     ret += *iter ;
01234   }
01235   ret += "]" ;
01236   return ret ;
01237 }
01238 
01239 
01240 
01241 
01242 //_____________________________________________________________________________
01243 string RooFactoryWSTool::processCreateVar(string& func, vector<string>& args)
01244 {  
01245   // Glue function between high-level syntax and low-level factory call to createVariable:
01246   // Process a parsed call to create a variable named 'func'
01247   // 
01248   // If initial token is non-numeric, a RooCategory will be created, and the args are interpreted
01249   // as either state names or 'name=id' assignments. Otherwise a RooRealvar is created and the
01250   // arg list is interpreted as follows:
01251   // If list has two args, these are interpreted as xmin,xmax
01252   // If list has three args, these are interpreted as xinit,xmin,xmax
01253   // If list has one arg, this is interpreted as xinit and the variable is set as constant
01254 
01255 
01256   // Determine if first arg is numeric
01257   string first = *(args.begin()) ;
01258   if (isdigit(first[0]) || first[0]=='.' || first[0]=='+' || first[0]=='-') {
01259     
01260     // Create a RooRealVar
01261     vector<string>::iterator ai = args.begin() ;
01262     if (args.size()==1) {
01263 
01264       // One argument, create constant variable with given value
01265       Double_t xinit = atof((ai)->c_str()) ;
01266       cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << endl ;
01267       RooRealVar tmp(func.c_str(),func.c_str(),xinit) ;
01268       tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
01269       if (_ws->import(tmp,Silence())) {
01270         logError() ;
01271       }
01272 
01273     } else if (args.size()==2) {
01274 
01275       // Two arguments, create variable with given range
01276       Double_t xlo = atof((ai++)->c_str()) ;
01277       Double_t xhi = atof(ai->c_str()) ;
01278       cxcoutD(ObjectHandling) << "CREATE variable " << func << " xlo = " << xlo << " xhi = " << xhi << endl ;
01279       RooRealVar tmp(func.c_str(),func.c_str(),xlo,xhi) ;
01280       tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
01281       if (_ws->import(tmp,Silence())) {
01282         logError() ;
01283       }
01284 
01285     } else if (args.size()==3) {
01286 
01287       // Three arguments, create variable with given initial value and range
01288       Double_t xinit = atof((ai++)->c_str()) ;
01289       Double_t xlo = atof((ai++)->c_str()) ;
01290       Double_t xhi = atof(ai->c_str()) ;
01291       cxcoutD(ObjectHandling) << "CREATE variable " << func << " xinit = " << xinit << " xlo = " << xlo << " xhi = " << xhi << endl ;
01292       RooRealVar tmp(func.c_str(),func.c_str(),xinit,xlo,xhi) ;
01293       tmp.setStringAttribute("factory_tag",varTag(func,args).c_str()) ;
01294       if (_ws->import(tmp,Silence())) {
01295         logError() ;
01296       }
01297     }
01298   } else {
01299 
01300     // Create a RooAbsCategory
01301     string allStates ;
01302     for (vector<string>::iterator ai = args.begin() ; ai!=args.end() ; ai++) {
01303       if (allStates.size()>0) {
01304         allStates += "," ;
01305       }
01306       allStates += *ai ;
01307     }
01308     createCategory(func.c_str(),allStates.c_str()) ;
01309 
01310   }
01311   return func ;
01312 }
01313       
01314 
01315 //_____________________________________________________________________________
01316 string RooFactoryWSTool::processCreateArg(string& func, vector<string>& args)
01317 {  
01318   // Glue function between high-level syntax and low-level factory call to createArg:
01319   // Process a parsed call to create a p.d.f named func
01320   //
01321   // The func arg is interpreted as ClassName::ObjectName and the arglist is passed
01322   // verbatim to createArg. The received arglist is expected to be fully reduced (i.e.
01323   // all inline object creations must have been compiled)
01324 
01325   // Allocate and fill work buffer
01326   char buf[1024] ;
01327   strlcpy(buf,func.c_str(),1024) ;
01328 
01329   // Split function part in class name and instance name
01330   char* save ;
01331   const char *className = strtok_r(buf,":",&save) ;
01332   const char *instName = strtok_r(0,":",&save) ;
01333   if (!className) className = "";
01334   if (!instName) instName = "" ;
01335 
01336   // Concatenate list of args into comma separated string
01337   char pargs[1024] ;
01338   pargs[0] = 0 ;
01339   vector<string>::iterator iter = args.begin() ;
01340   vector<string> pargv ;
01341   Int_t iarg(0) ;
01342   while(iter!=args.end()) {
01343     if (strlen(pargs)>0) strlcat(pargs,",",1024) ;
01344     _autoNamePrefix.push(Form("%s_%d",instName,iarg+1)) ;
01345     string tmp = processExpression(iter->c_str()) ;
01346     _autoNamePrefix.pop() ;
01347     strlcat(pargs,tmp.c_str(),1024) ;
01348     pargv.push_back(tmp) ;
01349     iter++ ;
01350     iarg++ ;
01351   }
01352 
01353   // Look up if func is a special
01354   for (map<string,IFace*>::iterator ii=hooks().begin() ; ii!=hooks().end() ; ii++) {
01355   }
01356   if (hooks().find(className) != hooks().end()) {
01357     IFace* iface = hooks()[className] ;
01358     return iface->create(*this, className,instName,pargv) ;
01359   }
01360 
01361   createArg(className,instName,pargs) ;
01362 
01363   return string(instName) ;
01364 }
01365       
01366 
01367 
01368 //_____________________________________________________________________________
01369 std::string RooFactoryWSTool::processMetaArg(std::string& func, std::vector<std::string>& args) 
01370 {
01371   // Concatenate list of args into comma separated string
01372   char pargs[1024] ;
01373   pargs[0] = 0 ;
01374   vector<string>::iterator iter = args.begin() ;
01375   vector<string> pargv ;
01376   while(iter!=args.end()) {
01377     if (strlen(pargs)>0) strlcat(pargs,",",1024) ;
01378     string tmp = processExpression(iter->c_str()) ;
01379     strlcat(pargs,tmp.c_str(),1024) ;
01380     pargv.push_back(tmp) ;
01381     iter++ ;
01382   }
01383 
01384   string ret = func+"("+pargs+")" ;  
01385   return ret ;
01386 }
01387 
01388 
01389 
01390 
01391 //_____________________________________________________________________________
01392 vector<string> RooFactoryWSTool::splitFunctionArgs(const char* funcExpr) 
01393 {
01394   // Allocate and fill work buffer
01395   char* buf = new char[strlen(funcExpr)+1] ; 
01396   strlcpy(buf,funcExpr,strlen(funcExpr)+1) ;
01397   char* bufptr = buf ;
01398 
01399   string func ;
01400   vector<string> args ;
01401 
01402   // Process token into arguments
01403   char* save ;
01404   char* tmpx = strtok_r(buf,"(",&save) ;  
01405   func = tmpx ? tmpx : "" ;
01406   char* p = strtok_r(0,"",&save) ;
01407   
01408   // Return here if token is fundamental
01409   if (!p) {
01410     delete[] buf ;
01411     return args ;
01412   }
01413 
01414   char* tok = p ;
01415   Int_t blevel=0 ;
01416   Bool_t litmode(kFALSE) ;
01417   while(*p) {
01418 
01419     // Keep track of opening and closing brackets
01420     if (*p=='{' || *p=='(' || *p=='[') blevel++ ;
01421     if (*p=='}' || *p==')' || *p==']') blevel-- ;
01422 
01423     // Keep track of string literals
01424     if (*p=='"' || *p=='\'') litmode = !litmode ;
01425 
01426 
01427     // If we encounter a comma at zero bracket level
01428     // finalize the current token as a completed argument
01429     // and start the next token
01430     if (!litmode && blevel==0 && ((*p)==',')) {
01431       *p = 0 ;
01432       args.push_back(tok) ;
01433       tok = p+1 ;
01434     }
01435 
01436     p++ ;
01437   }
01438 
01439   // If the last character was a closing bracket, kill
01440   // it in the buffer
01441   if (p>bufptr && *(p-1)==')') {
01442     *(p-1)=0 ;
01443   }
01444 
01445   // Finalize last token as argument
01446   string tmp = tok ;
01447   
01448   // If there is a suffix left in the work buffer attach it to 
01449   // this argument
01450   p = strtok_r(0,"",&save) ;
01451   if (p) tmp += p ;
01452   args.push_back(tmp) ;
01453 
01454   // Delete the work buffer
01455   delete[] buf ;
01456   
01457   return args ;
01458 }
01459 
01460 
01461 
01462 
01463 
01464 //_____________________________________________________________________________
01465 Bool_t RooFactoryWSTool::checkSyntax(const char* arg) 
01466 {
01467   // Perform basic syntax on given factory expression. If function returns
01468   // true syntax errors are found.
01469   
01470   // Count parentheses
01471   Int_t nParentheses(0), nBracket(0), nAccolade(0) ;
01472   const char* ptr = arg ;
01473   while(*ptr) {
01474     if (*ptr=='(') nParentheses++ ;
01475     if (*ptr==')') nParentheses-- ;
01476     if (*ptr=='[') nBracket++ ;
01477     if (*ptr==']') nBracket-- ;
01478     if (*ptr=='{') nAccolade++ ;
01479     if (*ptr=='}') nAccolade-- ;
01480     ptr++ ;
01481   }
01482   if (nParentheses!=0) {
01483     coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nParentheses>0?"(":")") << "' in expression" << endl ;
01484     return kTRUE ;
01485   }
01486   if (nBracket!=0) {
01487     coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nBracket>0?"[":"]") << "' in expression" << endl ;
01488     return kTRUE ;
01489   }
01490   if (nAccolade!=0) {
01491     coutE(ObjectHandling) << "RooFactoryWSTool::checkSyntax ERROR non-matching '" << (nAccolade>0?"{":"}") << "' in expression" << endl ;
01492     return kTRUE ;
01493   }
01494   return kFALSE ;
01495 }
01496 
01497 
01498 
01499 //_____________________________________________________________________________
01500 void RooFactoryWSTool::checkIndex(UInt_t idx) 
01501 {
01502   if (idx>_of->_args.size()-1) {
01503     throw string(Form("Need argument number %d, but only %d args are provided",idx,(Int_t)_of->_args.size())) ;
01504   }
01505 }
01506 
01507 
01508 
01509 //_____________________________________________________________________________
01510 RooAbsArg& RooFactoryWSTool::asARG(const char* arg) 
01511   {
01512   // CINT constructor interface, return constructor string argument #idx as RooAbsArg reference found in workspace
01513 
01514   // If arg is a numeric string, make a RooConst() of it here
01515   if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
01516     return RooConst(atof(arg)) ;
01517   }
01518 
01519   // Otherwise look it up by name in the workspace
01520   RooAbsArg* rarg = ws().arg(arg) ;
01521   if (!rarg) {
01522     throw string(Form("RooAbsArg named %s not found",arg)) ;
01523   }
01524   return *rarg ;
01525 }
01526 
01527 
01528 
01529 //_____________________________________________________________________________
01530 RooAbsReal& RooFactoryWSTool::asFUNC(const char* arg) 
01531 {
01532   // CINT constructor interface, return constructor string argument #idx as RooAbsReal reference found in workspace
01533 
01534   // If arg is a numeric string, make a RooConst() of it here
01535   if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
01536     return RooConst(atof(arg)) ;
01537   }
01538 
01539   RooAbsArg* rarg = ws().arg(arg) ;
01540   if (!rarg) {
01541     throw string(Form("RooAbsReal named %s not found",arg)) ;
01542   }
01543   RooAbsReal* real = dynamic_cast<RooAbsReal*>(rarg) ;
01544   if (!real) {
01545     throw string(Form("Object named %s is not of type RooAbsReal",arg)) ;
01546   }
01547   return *real ;
01548 }
01549 
01550 
01551 
01552 //_____________________________________________________________________________
01553 RooAbsRealLValue& RooFactoryWSTool::asVARLV(const char* arg) 
01554 {
01555   // CINT constructor interface, return constructor string argument #idx as RooAbsRealLValue reference found in workspace
01556 
01557   // If arg is a numeric string, throw error as lvalue is required
01558   if (arg[0]=='.' || arg[0]=='+' || arg[0] == '-' || isdigit(arg[0])) {
01559     throw string(Form("Numeric literal provided for argument (%s), but lvalue is required",arg)) ;
01560   }
01561 
01562   RooAbsArg* rarg = ws().arg(arg) ;
01563   if (!rarg) {
01564     throw string(Form("RooAbsRealLValue named %s not found",arg)) ;
01565   }
01566   RooAbsRealLValue* reallv = dynamic_cast<RooAbsRealLValue*>(rarg) ;
01567   if (!reallv) {
01568     throw string(Form("Object named %s is not of type RooAbsRealLValue",arg)) ;
01569   }
01570   return *reallv ;
01571 }
01572 
01573 
01574 
01575 //_____________________________________________________________________________
01576 RooRealVar& RooFactoryWSTool::asVAR(const char* arg) 
01577 {
01578   // CINT constructor interface, return constructor string argument #idx as RooRealVar reference found in workspace
01579 
01580   RooRealVar* var = ws().var(arg) ;
01581   if (!var) {
01582     throw string(Form("RooRealVar named %s not found",arg)) ;
01583   }
01584   return *var ;
01585 }
01586 
01587 
01588 
01589 
01590 //_____________________________________________________________________________
01591 RooAbsPdf& RooFactoryWSTool::asPDF(const char* arg) 
01592 {
01593   // CINT constructor interface, return constructor string argument #idx as RooAbsPdf reference found in workspace
01594 
01595   RooAbsPdf* pdf = ws().pdf(arg) ;
01596   if (!pdf) {
01597     throw string(Form("RooAbsPdf named %s not found",arg)) ;
01598   }
01599   return *pdf ;
01600 }
01601 
01602 
01603 
01604 
01605 //_____________________________________________________________________________
01606 RooResolutionModel& RooFactoryWSTool::asRMODEL(const char* arg) 
01607 {
01608   // CINT constructor interface, return constructor string argument #idx as RooResolutionModel reference found in workspace
01609 
01610   RooAbsArg* rarg = ws().arg(arg) ;
01611   if (!rarg) {
01612     throw string(Form("RooResolutionModel named %s not found",arg)) ;
01613   }
01614   RooResolutionModel * rmodel = dynamic_cast<RooResolutionModel*>(rarg) ;
01615   if (!rmodel) {
01616     throw string(Form("Object named %s is not of type RooResolutionModel",arg)) ;
01617   }
01618   return *rmodel ;
01619 }
01620 
01621 
01622 
01623 
01624 //_____________________________________________________________________________
01625 RooAbsCategory& RooFactoryWSTool::asCATFUNC(const char* arg) 
01626 {
01627   // CINT constructor interface, return constructor string argument #idx as RooAbsCategory reference found in workspace
01628 
01629   RooAbsArg* rarg = ws().arg(arg) ;
01630   if (!rarg) {
01631     throw string(Form("RooAbsCategory named %s not found",arg)) ;
01632   }
01633   RooAbsCategory* catf = dynamic_cast<RooAbsCategory*>(rarg) ;
01634   if (!catf) {
01635     throw string(Form("Object named %s is not of type RooAbsCategory",arg)) ;
01636   }
01637   return *catf ;
01638 }
01639 
01640 
01641 
01642 //_____________________________________________________________________________
01643 RooAbsCategoryLValue& RooFactoryWSTool::asCATLV(const char* arg) 
01644 {
01645   // CINT constructor interface, return constructor string argument #idx as RooAbsCategoryLValue reference found in workspace
01646 
01647   RooAbsArg* rarg = ws().arg(arg) ;
01648   if (!rarg) {
01649     throw string(Form("RooAbsCategoryLValue named %s not found",arg)) ;
01650   }
01651 
01652   RooAbsCategoryLValue* catlv = dynamic_cast<RooAbsCategoryLValue*>(rarg) ;
01653   if (!catlv) {
01654     throw string(Form("Object named %s is not of type RooAbsCategoryLValue",arg)) ;
01655   }
01656   return *catlv ;
01657 }
01658 
01659 
01660 
01661 //_____________________________________________________________________________
01662 RooCategory& RooFactoryWSTool::asCAT(const char* arg) 
01663 {
01664   // CINT constructor interface, return constructor string argument #idx as RooCategory reference found in workspace
01665 
01666   RooCategory* cat = ws().cat(arg) ;
01667   if (!cat) {
01668     throw string(Form("RooCategory named %s not found",arg)) ;
01669   }
01670   return *cat ;
01671 }
01672 
01673 
01674 
01675 
01676 
01677 //_____________________________________________________________________________
01678 RooArgSet RooFactoryWSTool::asSET(const char* arg) 
01679 {
01680   // CINT constructor interface, return constructor string argument #idx as RooArgSet of objects found in workspace
01681 
01682   char tmp[1024] ;
01683   strlcpy(tmp,arg,1024) ;
01684 
01685   RooArgSet s ;
01686   
01687   // If given object is not of {,,,} form, interpret given string as name of defined set
01688   if (arg[0]!='{') {
01689     const RooArgSet* defSet = ws().set(arg) ;
01690     if (defSet) {
01691       s.add(*defSet) ;
01692       return s ;
01693     }
01694   }
01695 
01696   char* save ;
01697   char* tok = strtok_r(tmp,",{}",&save) ;
01698   while(tok) {
01699 
01700     // If arg is a numeric string, make a RooConst() of it here
01701     if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
01702       s.add(RooConst(atof(tok))) ;
01703     } else {
01704       RooAbsArg* aarg = ws().arg(tok) ;
01705       if (aarg) {
01706         s.add(*aarg)  ;
01707       } else {
01708         throw string(Form("RooAbsArg named %s not found",tok)) ;
01709       }
01710     }
01711     tok = strtok_r(0,",{}",&save) ;
01712   }
01713 
01714   return s ;
01715 }
01716 
01717 
01718 
01719 //_____________________________________________________________________________
01720 RooArgList RooFactoryWSTool::asLIST(const char* arg) 
01721 {
01722   // CINT constructor interface, return constructor string argument #idx as RooArgList of objects found in workspace
01723 
01724   char tmp[1024] ;
01725   strlcpy(tmp,arg,1024) ;
01726 
01727   RooArgList l ;
01728   char* save ;
01729   char* tok = strtok_r(tmp,",{}",&save) ;
01730   while(tok) {
01731 
01732     // If arg is a numeric string, make a RooConst() of it here
01733     if (tok[0]=='.' || tok[0]=='+' || tok[0] == '-' || isdigit(tok[0])) {
01734       l.add(RooConst(atof(tok))) ;
01735     } else {
01736       RooAbsArg* aarg = ws().arg(tok) ;
01737       if (aarg) {
01738         l.add(*aarg)  ;
01739       } else {
01740         throw string(Form("RooAbsArg named %s not found",tok)) ;
01741       }
01742     }
01743     tok = strtok_r(0,",{}",&save) ;
01744   }
01745   
01746   return l ;
01747 }
01748 
01749 
01750 
01751 //_____________________________________________________________________________
01752 RooAbsData& RooFactoryWSTool::asDATA(const char* arg) 
01753 {
01754   // CINT constructor interface, return constructor string argument #idx as RooAbsData object found in workspace
01755 
01756   RooAbsData* data = ws().data(arg) ;
01757   if (!data) {
01758       throw string(Form("RooAbsData named %s not found",arg)) ;    
01759   }
01760   return *data ;
01761 }
01762 
01763 
01764 
01765 //_____________________________________________________________________________
01766 RooDataHist& RooFactoryWSTool::asDHIST(const char* arg) 
01767 {
01768   // CINT constructor interface, return constructor string argument #idx as RooDataHist object found in workspace
01769 
01770   RooAbsData* data = ws().data(arg) ;
01771   if (!data) {
01772     throw string(Form("RooAbsData named %s not found",arg)) ;    
01773   }
01774   RooDataHist* hist = dynamic_cast<RooDataHist*>(data) ;
01775   if (!hist) {
01776     throw string(Form("Dataset named %s is not of type RooDataHist",arg)) ;    
01777   }
01778   return *hist ;
01779 }
01780 
01781 
01782 //_____________________________________________________________________________
01783 RooDataSet& RooFactoryWSTool::asDSET(const char* arg) 
01784 {
01785   // CINT constructor interface, return constructor string argument #idx as RooDataSet object found in workspace
01786 
01787   RooAbsData* data = ws().data(arg) ;
01788   if (!data) {
01789     throw string(Form("RooAbsData named %s not found",arg)) ;    
01790   }
01791   RooDataSet* dset = dynamic_cast<RooDataSet*>(data) ;
01792   if (!dset) {
01793     throw string(Form("Dataset named %s is not of type RooDataSet",arg)) ;    
01794   }
01795   return *dset ;
01796 }
01797 
01798 
01799 
01800 //_____________________________________________________________________________
01801 TObject& RooFactoryWSTool::asOBJ(const char* arg)
01802 {
01803   TObject* obj = ws().obj(arg) ;
01804   if (!obj) {
01805     throw string(Form("Object named %s not found",arg)) ;    
01806   }
01807   return *obj ;
01808 }
01809 
01810 
01811 
01812 //_____________________________________________________________________________
01813 const char* RooFactoryWSTool::asSTRING(const char* arg) 
01814 {
01815   // CINT constructor interface, return constructor string argument #idx as const char* 
01816 
01817   static vector<string> cbuf(10) ;
01818   static unsigned int cbuf_idx = 0 ;
01819 
01820   // Handle empty string case: return null pointer
01821   if (arg==0 || strlen(arg)==0) {
01822     return 0 ;
01823   }
01824   
01825   // Fill cyclical buffer entry with quotation marked stripped version of string literal
01826   // and return pointer to stripped buffer
01827   cbuf[cbuf_idx].clear() ;
01828   const char* p = arg+1 ;
01829   while(*p && (*p) != '"' && (*p) !='\'' ) {
01830     cbuf[cbuf_idx] += *(p++) ;
01831   }  
01832   const char* ret = cbuf[cbuf_idx].c_str() ;
01833 
01834   // Increment buffer pointer by one
01835   cbuf_idx++ ;
01836   if (cbuf_idx==cbuf.size()) cbuf_idx=0 ;
01837 
01838   return ret ;
01839 }
01840 
01841 
01842 //_____________________________________________________________________________
01843 Int_t RooFactoryWSTool::asINT(const char* arg) 
01844 {
01845   // CINT constructor interface, return constructor string argument #idx as Int_t
01846 
01847   return atoi(arg) ;
01848 }
01849 
01850 
01851 //_____________________________________________________________________________
01852 Double_t RooFactoryWSTool::asDOUBLE(const char* arg) 
01853 {
01854   // CINT constructor interface, return constructor string argument #idx as Double_t
01855 
01856   return atof(arg) ;
01857 }
01858 
01859 
01860 //_____________________________________________________________________________
01861 void RooFactoryWSTool::registerSpecial(const char* typeName, RooFactoryWSTool::IFace* iface) 
01862 {
01863   // Register foreign special objects in factory
01864   hooks()[typeName] = iface ;
01865 }
01866 
01867 
01868 
01869 //_____________________________________________________________________________
01870 std::map<std::string,RooFactoryWSTool::IFace*>& RooFactoryWSTool::hooks() 
01871 {
01872   if (_hooks) return *_hooks ;
01873   _hooks = new map<string,IFace*> ;
01874   return *_hooks ;
01875 }
01876 
01877 
01878 
01879 //_____________________________________________________________________________
01880 std::string RooFactoryWSTool::SpecialsIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instName, std::vector<std::string> args)
01881 {
01882   // Concatenate list of args into comma separated string
01883   char pargs[1024] ;
01884   pargs[0] = 0 ;
01885   vector<string>::iterator iter = args.begin() ;
01886   vector<string> pargv ;
01887   while(iter!=args.end()) {
01888     if (strlen(pargs)>0) strlcat(pargs,",",1024) ;
01889     string tmp = ft.processExpression(iter->c_str()) ;
01890     strlcat(pargs,tmp.c_str(),1024) ;
01891     pargv.push_back(tmp) ;
01892     iter++ ;
01893   }
01894 
01895   // Handling of special operator pdf class names
01896   string cl(typeName) ;
01897   if (cl=="SUM") {
01898 
01899     // SUM::name[a*A,b*B,C]
01900     ft.add(instName,pargs,kFALSE) ;
01901 
01902   } else if (cl=="RSUM") {
01903 
01904     // RSUM::name[a*A,b*B,C]
01905     ft.add(instName,pargs,kTRUE) ;
01906 
01907   } else if (cl=="ASUM") {
01908 
01909     // ASUM::name[a*A,b*B,C]
01910     ft.amplAdd(instName,pargs) ;
01911 
01912   } else if (cl=="PROD") {
01913 
01914     // PROD::name[A,B,C]
01915     ft.prod(instName,pargs) ;
01916 
01917   } else if (cl=="SIMUL") {
01918 
01919     // PROD::name[cat,state=Pdf,...]
01920     if (pargv.size()>1) {
01921       ft.simul(instName,pargv[0].c_str(),strchr(pargs,',')+1) ;
01922     } else {
01923       throw string(Form("Need at least two arguments in call to SIMUL::%s, have %d: %s",instName,(Int_t)pargv.size(),pargs)) ;
01924     }
01925 
01926   } else if (cl=="EXPR") {
01927     
01928     // EXPR::name['expr',var,var,...]
01929     if (args.size()<=2) {
01930       ft.createArg("RooGenericPdf",instName,pargs) ;
01931     } else {      
01932       char genargs[1024] ;
01933       strlcpy(genargs,args[0].c_str(),1024) ;      
01934       strlcat(genargs,",{",1024) ;
01935       for (UInt_t i=1 ; i<args.size() ; i++) {
01936         if (i!=1) strlcat(genargs,",",1024) ;
01937         strlcat(genargs,args[i].c_str(),1024) ;
01938       }
01939       strlcat(genargs,"}",1024) ;
01940       ft.createArg("RooGenericPdf",instName,genargs) ;
01941     }
01942   
01943   } else if (cl=="FCONV") {
01944 
01945     // FCONV::name[var,pdf1,pdf2]
01946     ft.createArg("RooFFTConvPdf",instName,pargs) ;
01947   
01948   } else if (cl=="NCONV") {
01949 
01950     // NCONV::name[var,pdf1,pdf2]
01951     ft.createArg("RooNumConvPdf",instName,pargs) ;
01952   
01953   } else if (cl=="sum") {
01954     
01955     // sum::name[a,b,c]
01956     ft.addfunc(instName,pargs) ;
01957 
01958   } else if (cl=="prod") {
01959 
01960     // prod::name[a,b,c]
01961     ft.prodfunc(instName,pargs) ;
01962     
01963   } else if (cl=="expr") {
01964 
01965     // expr::name['expr',var,var,...]
01966     if (args.size()<=2) {
01967       ft.createArg("RooFormulaVar",instName,pargs) ;
01968     } else {      
01969       char genargs[1024] ;
01970       strlcpy(genargs,args[0].c_str(),1024) ;      
01971       strlcat(genargs,",{",1024) ;
01972       for (UInt_t i=1 ; i<args.size() ; i++) {
01973         if (i!=1) strlcat(genargs,",",1024) ;
01974         strlcat(genargs,args[i].c_str(),1024) ;
01975       }
01976       strlcat(genargs,"}",1024) ;
01977       ft.createArg("RooFormulaVar",instName,genargs) ;
01978     }
01979 
01980   } else if (cl=="nconv") {
01981 
01982     // nconv::name[var,pdf1,pdf2]
01983     ft.createArg("RooNumConvolution",instName,pargs) ;
01984   
01985   } else if (cl=="nll") {
01986 
01987     // nll::name[pdf,data]
01988     RooNLLVar nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDATA(pargv[1].c_str())) ;
01989     if (ft.ws().import(nll,Silence())) ft.logError() ;
01990     
01991   } else if (cl=="chi2") {
01992 
01993     // chi2::name[pdf,data]
01994     RooChi2Var nll(instName,instName,ft.asPDF(pargv[0].c_str()),ft.asDHIST(pargv[1].c_str())) ;
01995     if (ft.ws().import(nll,Silence())) ft.logError() ;
01996     
01997   } else if (cl=="profile") {
01998 
01999     // profile::name[func,vars]
02000     ft.createArg("RooProfileLL",instName,pargs) ;
02001 
02002   } else if (cl=="dataobs") {
02003 
02004     // dataobs::name[dset,func]
02005     RooAbsArg* funcClone = static_cast<RooAbsArg*>(ft.asARG(pargv[1].c_str()).clone(instName)) ;
02006     RooAbsArg* arg = ft.asDSET(pargv[0].c_str()).addColumn(*funcClone) ;
02007     if (!ft.ws().fundArg(arg->GetName())) {
02008       if (ft.ws().import(*arg,Silence())) ft.logError() ;
02009     }
02010     delete funcClone ;
02011 
02012   } else if (cl=="int") {    
02013     
02014     // int::name[func,intobs]
02015     // int::name[func,intobs|range]
02016     // int::name[func,intobs,normobs]
02017     // int::name[func,intobs|range,normobs]
02018 
02019     if (pargv.size()<2 || pargv.size()>3) {
02020       throw string(Form("int::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
02021     }
02022 
02023     RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
02024 
02025     char buf[256] ;
02026     strlcpy(buf,pargv[1].c_str(),256) ;
02027     char* save ;
02028     const char* intobs = strtok_r(buf,"|",&save) ;
02029     if (!intobs) intobs="" ;
02030 
02031     const char* range = strtok_r(0,"",&save) ;
02032     if (!range) range="" ;
02033 
02034     RooAbsReal* integral = 0 ;
02035     if (pargv.size()==2) {
02036       if (range && strlen(range)) {
02037         integral = func.createIntegral(ft.asSET(intobs),Range(range)) ;
02038       } else {
02039         integral = func.createIntegral(ft.asSET(intobs)) ;
02040       }
02041     } else {
02042       if (range && strlen(range)) {
02043         integral = func.createIntegral(ft.asSET(intobs),Range(range),NormSet(ft.asSET(pargv[2].c_str()))) ;
02044       } else {
02045         integral = func.createIntegral(ft.asSET(intobs),NormSet(ft.asSET(pargv[2].c_str()))) ;
02046       }
02047     }
02048 
02049     integral->SetName(instName) ;
02050     if (ft.ws().import(*integral,Silence())) ft.logError() ;
02051     
02052   } else if (cl=="deriv") {
02053     
02054     // derive::name[func,obs,order]
02055 
02056     if (pargv.size()<2 || pargv.size()>3) {
02057       throw string(Form("deriv::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
02058     }
02059 
02060     RooAbsReal& func = ft.asFUNC(pargv[0].c_str()) ;
02061 
02062     RooAbsReal* derivative(0) ;
02063     if (pargv.size()==2) {
02064       derivative = func.derivative(ft.asVAR(pargv[1].c_str()),1) ;
02065     } else {
02066       derivative = func.derivative(ft.asVAR(pargv[1].c_str()),ft.asINT(pargv[2].c_str())) ;
02067     }
02068 
02069     derivative->SetName(instName) ;
02070     if (ft.ws().import(*derivative,Silence())) ft.logError() ;
02071 
02072   } else if (cl=="cdf") {
02073 
02074     // cdf::name[pdf,obs,extranormobs]
02075 
02076     if (pargv.size()<2 || pargv.size()>3) {
02077       throw string(Form("cdf::%s, requires 2 or 3 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
02078     }
02079 
02080     RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
02081 
02082     RooAbsReal* cdf(0) ;
02083     if (pargv.size()==2) {
02084       cdf = pdf.createCdf(ft.asSET(pargv[1].c_str())) ;
02085     } else {
02086       cdf = pdf.createCdf(ft.asSET(pargv[1].c_str()),ft.asSET(pargv[2].c_str())) ;
02087     }
02088 
02089     cdf->SetName(instName) ;
02090     if (ft.ws().import(*cdf,Silence())) ft.logError() ;
02091 
02092 
02093   } else if (cl=="PROJ") {
02094 
02095     // PROJ::name(pdf,intobs)
02096     if (pargv.size()!=2) {
02097       throw string(Form("PROJ::%s, requires 2 arguments, have %d arguments",instName,(Int_t)pargv.size())) ;
02098     }
02099 
02100     RooAbsPdf& pdf = ft.asPDF(pargv[0].c_str()) ;
02101     RooAbsPdf* projection = pdf.createProjection(ft.asSET(pargv[1].c_str())) ;
02102     projection->SetName(instName) ;
02103 
02104     if (ft.ws().import(*projection,Silence())) ft.logError() ;
02105 
02106   } else if (cl=="set") {
02107 
02108     // set::name(arg,arg,...)
02109     if (ft.ws().defineSet(instName,pargs)) {
02110       ft.logError() ;
02111       return string(instName) ;
02112     }
02113     
02114   } else {
02115 
02116     throw string(Form("RooFactoryWSTool::SpecialsIFace::create() ERROR: Unknown meta-type %s",typeName)) ;
02117 
02118   }
02119   return string(instName) ;    
02120 }

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