RooClassFactory.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooClassFactory.cxx 36230 2010-10-09 20:21:02Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 // RooClassFactory 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 #include "TClass.h"
00030 #include "RooClassFactory.h"
00031 #include "RooClassFactory.h"
00032 #include "RooAbsReal.h"
00033 #include "RooAbsCategory.h"
00034 #include "RooArgList.h"
00035 #include "RooMsgService.h"
00036 #include "TInterpreter.h"
00037 #include "RooWorkspace.h"
00038 #include "RooGlobalFunc.h"
00039 #include "RooAbsPdf.h"
00040 #include <fstream>
00041 #include <vector>
00042 #include <string>
00043 
00044 using namespace std ;
00045 
00046 ClassImp(RooClassFactory)
00047 ;
00048 
00049 static Int_t init()
00050 {
00051   RooFactoryWSTool::IFace* iface = new RooClassFactory::ClassFacIFace ;
00052   RooFactoryWSTool::registerSpecial("CEXPR",iface) ;
00053   RooFactoryWSTool::registerSpecial("cexpr",iface) ;
00054   return 0 ;
00055 }
00056 static Int_t dummy = init() ;
00057 
00058 
00059 
00060 
00061 //_____________________________________________________________________________
00062 RooClassFactory::RooClassFactory()
00063 {
00064   // Default constructor
00065 }
00066 
00067 
00068 
00069 //_____________________________________________________________________________
00070 RooClassFactory::~RooClassFactory()
00071 {
00072   // Destructor
00073 }
00074 
00075 
00076 
00077 //_____________________________________________________________________________
00078 Bool_t RooClassFactory::makeAndCompilePdf(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
00079 {
00080 
00081   string realArgNames,catArgNames ;
00082   TIterator* iter = vars.createIterator() ;
00083   RooAbsArg* arg ;
00084   while((arg=(RooAbsArg*)iter->Next())) {
00085     if (dynamic_cast<RooAbsReal*>(arg)) {
00086       if (realArgNames.size()>0) realArgNames += "," ;
00087       realArgNames += arg->GetName() ;
00088     } else if (dynamic_cast<RooAbsCategory*>(arg)) {
00089       if (catArgNames.size()>0) catArgNames += "," ;
00090       catArgNames += arg->GetName() ;
00091     } else {
00092       oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompilePdf ERROR input argument " << arg->GetName()
00093                                               << " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
00094     }
00095   }
00096   delete iter ;
00097 
00098   Bool_t ret = makePdf(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,kFALSE,intExpression) ;
00099   if (ret) {
00100     return ret ;
00101   }
00102 
00103   if (gInterpreter->GetRootMapFiles()==0) {
00104     gInterpreter->EnableAutoLoading() ;
00105   }
00106 
00107   TInterpreter::EErrorCode ecode;
00108   gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
00109   return (ecode!=TInterpreter::kNoError) ;
00110 }
00111 
00112 
00113 
00114 //_____________________________________________________________________________
00115 Bool_t RooClassFactory::makeAndCompileFunction(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
00116 {
00117   // Write, compile and load code for a RooAbsReal implementation with
00118   // class name 'name', taking all elements of 'vars' as constructor
00119   // arguments. The initial value expression is taken to be
00120   // 'expression' which can be any one-line C++ expression in terms of
00121   // variables that occur in 'vars'. You can add optional expressions
00122   // for analytical integrals to be advertised by your class in the
00123   // syntax
00124   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00125   // where <intObsName> a name of the observable integrated over and
00126   // <CPPAnaIntExpression> is the C++ expression that calculates that
00127   // integral.
00128 
00129   string realArgNames,catArgNames ;
00130   TIterator* iter = vars.createIterator() ;
00131   RooAbsArg* arg ;
00132   while((arg=(RooAbsArg*)iter->Next())) {
00133     if (dynamic_cast<RooAbsReal*>(arg)) {
00134       if (realArgNames.size()>0) realArgNames += "," ;
00135       realArgNames += arg->GetName() ;
00136     } else if (dynamic_cast<RooAbsCategory*>(arg)) {
00137       if (catArgNames.size()>0) catArgNames += "," ;
00138       catArgNames += arg->GetName() ;
00139     } else {
00140       oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompileFunction ERROR input argument " << arg->GetName()
00141                                             << " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
00142     }
00143   }
00144   delete iter ;
00145 
00146   Bool_t ret = makeFunction(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,intExpression) ;
00147   if (ret) {
00148     return ret ;
00149   }
00150 
00151   if (gInterpreter->GetRootMapFiles()==0) {
00152     gInterpreter->EnableAutoLoading() ;
00153   }
00154 
00155   TInterpreter::EErrorCode ecode;
00156   gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
00157   return (ecode!=TInterpreter::kNoError) ;
00158 }
00159 
00160 
00161 //_____________________________________________________________________________
00162 RooAbsReal* RooClassFactory::makeFunctionInstance(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
00163 {
00164   // Write, compile and load code and instantiate object for a
00165   // RooAbsReal implementation with class name 'name', taking all
00166   // elements of 'vars' as constructor arguments. The initial value
00167   // expression is taken to be 'expression' which can be any one-line
00168   // C++ expression in terms of variables that occur in 'vars'.
00169   //
00170   // The returned object is an instance of the object you just defined
00171   // connected to the variables listed in 'vars'. The name of the
00172   // object is 'name', its class name Roo<name>Class.
00173   //
00174   // This function is an effective compiled replacement of RooFormulaVar
00175   //
00176   // You can add optional expressions for analytical integrals to be
00177   // advertised by your class in the syntax
00178   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00179   // where <intObsName> a name of the observable integrated over and
00180   // <CPPAnaIntExpression> is the C++ expression that calculates that
00181   // integral.
00182 
00183   // Construct unique class name for this function expression
00184   string tmpName(name) ;
00185   tmpName[0] = toupper(tmpName[0]) ;
00186   string className = Form("Roo%sFunc",tmpName.c_str()) ;
00187 
00188   return makeFunctionInstance(className.c_str(),name,expression,vars,intExpression) ;
00189 }
00190 
00191 //_____________________________________________________________________________
00192 RooAbsReal* RooClassFactory::makeFunctionInstance(const char* className, const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
00193 {
00194   // Write, compile and load code and instantiate object for a
00195   // RooAbsReal implementation with class name 'name', taking all
00196   // elements of 'vars' as constructor arguments. The initial value
00197   // expression is taken to be 'expression' which can be any one-line
00198   // C++ expression in terms of variables that occur in 'vars'.
00199   //
00200   // The returned object is an instance of the object you just defined
00201   // connected to the variables listed in 'vars'. The name of the
00202   // object is 'name', its class name Roo<name>Class.
00203   //
00204   // This function is an effective compiled replacement of RooFormulaVar
00205   //
00206   // You can add optional expressions for analytical integrals to be
00207   // advertised by your class in the syntax
00208   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00209   // where <intObsName> a name of the observable integrated over and
00210   // <CPPAnaIntExpression> is the C++ expression that calculates that
00211   // integral.
00212 
00213   if (gInterpreter->GetRootMapFiles()==0) {
00214     gInterpreter->EnableAutoLoading() ;
00215   }
00216 
00217   // Use class factory to compile and link specialized function
00218   Bool_t error = makeAndCompileFunction(className,expression,vars,intExpression) ;
00219 
00220   // Check that class was created OK
00221   if (error) {
00222     RooErrorHandler::softAbort() ;
00223   }
00224 
00225   // Create CINT line that instantiates specialized object
00226   string line = Form("new %s(\"%s\",\"%s\"",className,name,name) ;
00227 
00228   // Make list of pointer values (represented in hex ascii) to be passed to cint
00229   // Note that the order of passing arguments must match the convention in which
00230   // the class code is generated: first all reals, then all categories
00231 
00232   TIterator* iter = vars.createIterator() ;
00233   string argList ;
00234   // First pass the RooAbsReal arguments in the list order
00235   RooAbsArg* var ;
00236   while((var=(RooAbsArg*)iter->Next())) {
00237     if (dynamic_cast<RooAbsReal*>(var)) {
00238       argList += Form(",*((RooAbsReal*)%p)",var) ;
00239     }
00240   }
00241   iter->Reset() ;
00242   // Next pass the RooAbsCategory arguments in the list order
00243   while((var=(RooAbsArg*)iter->Next())) {
00244     if (dynamic_cast<RooAbsCategory*>(var)) {
00245       argList += Form(",*((RooAbsCategory*)%p)",var) ;
00246     }
00247   }
00248   delete iter ;
00249 
00250   line += argList + ") ;" ;
00251 
00252   // Let CINT instantiate specialized formula
00253   return (RooAbsReal*) gInterpreter->ProcessLineSynch(line.c_str()) ;
00254 }
00255 
00256 
00257 
00258 
00259 //_____________________________________________________________________________
00260 RooAbsPdf* RooClassFactory::makePdfInstance(const char* name, const char* expression,
00261                                             const RooArgList& vars, const char* intExpression)
00262 {
00263   // Write, compile and load code and instantiate object for a
00264   // RooAbsPdf implementation with class name 'name', taking all
00265   // elements of 'vars' as constructor arguments. The initial value
00266   // expression is taken to be 'expression' which can be any one-line
00267   // C++ expression in terms of variables that occur in 'vars'.
00268   //
00269   // The returned object is an instance of the object you just defined
00270   // connected to the variables listed in 'vars'. The name of the
00271   // object is 'name', its class name Roo<name>Class.
00272   //
00273   // This function is an effective compiled replacement of RooGenericPdf
00274   //
00275   // You can add optional expressions for analytical integrals to be
00276   // advertised by your class in the syntax
00277   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00278   // where <intObsName> a name of the observable integrated over and
00279   // <CPPAnaIntExpression> is the C++ expression that calculates that
00280   // integral.
00281 
00282   // Construct unique class name for this function expression
00283   string tmpName(name) ;
00284   tmpName[0] = toupper(tmpName[0]) ;
00285   string className = Form("Roo%sPdf",tmpName.c_str()) ;
00286 
00287   return makePdfInstance(className.c_str(),name,expression,vars,intExpression) ;
00288 }
00289 
00290 //_____________________________________________________________________________
00291 RooAbsPdf* RooClassFactory::makePdfInstance(const char* className, const char* name, const char* expression,
00292                                             const RooArgList& vars, const char* intExpression)
00293 {
00294   // Write, compile and load code and instantiate object for a
00295   // RooAbsPdf implementation with class name 'name', taking all
00296   // elements of 'vars' as constructor arguments. The initial value
00297   // expression is taken to be 'expression' which can be any one-line
00298   // C++ expression in terms of variables that occur in 'vars'.
00299   //
00300   // The returned object is an instance of the object you just defined
00301   // connected to the variables listed in 'vars'. The name of the
00302   // object is 'name', its class name Roo<name>Class.
00303   //
00304   // This function is an effective compiled replacement of RooGenericPdf
00305   //
00306   // You can add optional expressions for analytical integrals to be
00307   // advertised by your class in the syntax
00308   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00309   // where <intObsName> a name of the observable integrated over and
00310   // <CPPAnaIntExpression> is the C++ expression that calculates that
00311   // integral.
00312 
00313   if (gInterpreter->GetRootMapFiles()==0) {
00314     gInterpreter->EnableAutoLoading() ;
00315   }
00316 
00317   // Use class factory to compile and link specialized function
00318   Bool_t error = makeAndCompilePdf(className,expression,vars,intExpression) ;
00319 
00320   // Check that class was created OK
00321   if (error) {
00322     RooErrorHandler::softAbort() ;
00323   }
00324 
00325   // Create CINT line that instantiates specialized object
00326   string line = Form("new %s(\"%s\",\"%s\"",className,name,name) ;
00327 
00328   // Make list of pointer values (represented in hex ascii) to be passed to cint
00329   // Note that the order of passing arguments must match the convention in which
00330   // the class code is generated: first all reals, then all categories
00331 
00332   TIterator* iter = vars.createIterator() ;
00333   string argList ;
00334   // First pass the RooAbsReal arguments in the list order
00335   RooAbsArg* var ;
00336   while((var=(RooAbsArg*)iter->Next())) {
00337     if (dynamic_cast<RooAbsReal*>(var)) {
00338       argList += Form(",*((RooAbsReal*)%p)",var) ;
00339     }
00340   }
00341   iter->Reset() ;
00342   // Next pass the RooAbsCategory arguments in the list order
00343   while((var=(RooAbsArg*)iter->Next())) {
00344     if (dynamic_cast<RooAbsCategory*>(var)) {
00345       argList += Form(",*((RooAbsCategory*)%p)",var) ;
00346     }
00347   }
00348   delete iter ;
00349 
00350   line += argList + ") ;" ;
00351 
00352   // Let CINT instantiate specialized formula
00353   return (RooAbsPdf*) gInterpreter->ProcessLineSynch(line.c_str()) ;
00354 }
00355 
00356 
00357 
00358 //_____________________________________________________________________________
00359 Bool_t RooClassFactory::makePdf(const char* name, const char* argNames, const char* catArgNames, const char* expression,
00360                                 Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
00361 {
00362   // Write code for a RooAbsPdf implementation with class name 'name',
00363   // taking RooAbsReal arguments with names listed in argNames and
00364   // RooAbsCategory arguments with names listed in catArgNames as
00365   // constructor arguments (use a comma separated list for multiple
00366   // arguments). The initial value expression is taken to be
00367   // 'expression' which can be any one-line C++ expression in terms of
00368   // variables that occur in 'vars'. Skeleton code for handling of
00369   // analytical integrals is added if hasAnaInt is true. You can add
00370   // optional expressions for analytical integrals to be advertised by
00371   // your class in the syntax
00372   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00373   // where <intObsName> a name of the observable integrated over and
00374   // <CPPAnaIntExpression> is the C++ expression that calculates that
00375   // integral. Skeleton code for internal event generation is added
00376   // if hasIntGen is true
00377   //
00378 
00379   return makeClass("RooAbsPdf",name,argNames,catArgNames,expression,hasAnaInt,hasIntGen,intExpression) ;
00380 }
00381 
00382 
00383 //_____________________________________________________________________________
00384 Bool_t RooClassFactory::makeFunction(const char* name, const char* argNames, const char* catArgNames, const char* expression, Bool_t hasAnaInt, const char* intExpression)
00385 {
00386   // Write code for a RooAbsReal implementation with class name 'name',
00387   // taking RooAbsReal arguments with names listed in argNames and
00388   // RooAbsCategory arguments with names listed in catArgNames as
00389   // constructor arguments (use a comma separated list for multiple
00390   // arguments). The initial value expression is taken to be
00391   // 'expression' which can be any one-line C++ expression in terms of
00392   // variables that occur in 'vars'. Skeleton code for handling of
00393   // analytical integrals is added if hasAnaInt is true. You can add
00394   // optional expressions for analytical integrals to be advertised by
00395   // your class in the syntax
00396   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00397   // where <intObsName> a name of the observable integrated over and
00398   // <CPPAnaIntExpression> is the C++ expression that calculates that
00399   // integral.
00400 
00401   return makeClass("RooAbsReal",name,argNames,catArgNames,expression,hasAnaInt,kFALSE,intExpression) ;
00402 }
00403 
00404 
00405 //_____________________________________________________________________________
00406 Bool_t RooClassFactory::makeClass(const char* baseName, const char* className, const char* realArgNames, const char* catArgNames,
00407                                   const char* expression,  Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
00408 {
00409   // Write code for a 'baseName' implementation with class name 'className',
00410   // taking RooAbsReal arguments with names listed in argNames and
00411   // RooAbsCategory arguments with names listed in catArgNames as
00412   // constructor arguments (use a comma separated list for multiple
00413   // arguments). The initial value expression is taken to be
00414   // 'expression' which can be any one-line C++ expression in terms of
00415   // variables that occur in 'vars'. Skeleton code for handling of
00416   // analytical integrals is added if hasAnaInt is true. You can add
00417   // optional expressions for analytical integrals to be advertised by
00418   // your class in the syntax
00419   // "<intObsName>:<CPPAnaIntExpression>;<intObsName,intObsName>:<CPPAnaIntExpression>"
00420   // where <intObsName> a name of the observable integrated over and
00421   // <CPPAnaIntExpression> is the C++ expression that calculates that
00422   // integral. Skeleton code for internal event generation is added
00423   // if hasIntGen is true
00424   //
00425 
00426   // Check that arguments were given
00427   if (!baseName) {
00428     oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a base class name must be given" << endl ;
00429     return kTRUE ;
00430   }
00431 
00432   if (!className) {
00433     oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a class name must be given" << endl ;
00434     return kTRUE ;
00435   }
00436 
00437   if ((!realArgNames || !*realArgNames) && (!catArgNames || !*catArgNames)) {
00438     oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << endl ;
00439     return kTRUE ;
00440   }
00441 
00442   if (intExpression && !hasAnaInt) {
00443     oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR no analytical integration code requestion, but expression for analytical integral provided" << endl ;
00444     return kTRUE ;
00445   }
00446 
00447   // Parse comma separated list of argument names into list of strings
00448   vector<string> alist ;
00449   vector<bool> isCat ;
00450 
00451   if (realArgNames && *realArgNames) {
00452     char* buf = new char[strlen(realArgNames)+1] ;
00453     strlcpy(buf,realArgNames,strlen(realArgNames)+1) ;
00454     char* token = strtok(buf,",") ;
00455     while(token) {
00456       alist.push_back(token) ;
00457       isCat.push_back(false) ;
00458       token = strtok(0,",") ;
00459     }
00460     delete[] buf ;
00461   }
00462   if (catArgNames && *catArgNames) {
00463     char* buf = new char[strlen(catArgNames)+1] ;
00464     strlcpy(buf,catArgNames,strlen(catArgNames)+1) ;
00465     char* token = strtok(buf,",") ;
00466     while(token) {
00467       alist.push_back(token) ;
00468       isCat.push_back(true) ;
00469       token = strtok(0,",") ;
00470     }
00471     delete[] buf ;
00472   }
00473 
00474   TString impFileName(className), hdrFileName(className) ;
00475   impFileName += ".cxx" ;
00476   hdrFileName += ".h" ;
00477 
00478   TString ifdefName(className) ;
00479   ifdefName.ToUpper() ;
00480 
00481   ofstream hf(hdrFileName) ;
00482   hf << "/*****************************************************************************" << endl
00483      << " * Project: RooFit                                                           *" << endl
00484      << " *                                                                           *" << endl
00485      << "  * This code was autogenerated by RooClassFactory                            * " << endl
00486      << " *****************************************************************************/" << endl
00487      << endl
00488      << "#ifndef " << ifdefName << endl
00489      << "#define " << ifdefName << endl
00490      << "" << endl
00491      << "#include \"" << baseName << ".h\"" << endl
00492      << "#include \"RooRealProxy.h\"" << endl
00493      << "#include \"RooCategoryProxy.h\"" << endl
00494      << "#include \"RooAbsReal.h\"" << endl
00495      << "#include \"RooAbsCategory.h\"" << endl
00496      << " " << endl
00497      << "class " << className << " : public " << baseName << " {" << endl
00498      << "public:" << endl
00499      << "  " << className << "() {} ; " << endl
00500      << "  " << className << "(const char *name, const char *title," << endl ;
00501 
00502   // Insert list of input arguments
00503   unsigned int i ;
00504   for (i=0 ; i<alist.size() ; i++) {
00505     if (!isCat[i]) {
00506       hf << "         RooAbsReal& _" ;
00507     } else {
00508       hf << "         RooAbsCategory& _" ;
00509     }
00510     hf << alist[i] ;
00511     if (i==alist.size()-1) {
00512       hf << ");" << endl ;
00513     } else {
00514       hf << "," << endl ;
00515     }
00516   }
00517 
00518   hf << "  " << className << "(const " << className << "& other, const char* name=0) ;" << endl
00519      << "  virtual TObject* clone(const char* newname) const { return new " << className << "(*this,newname); }" << endl
00520      << "  inline virtual ~" << className << "() { }" << endl
00521      << endl ;
00522 
00523   if (hasAnaInt) {
00524     hf << "  Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;" << endl
00525        << "  Double_t analyticalIntegral(Int_t code, const char* rangeName=0) const ;" << endl
00526        << "" << endl ;
00527   }
00528 
00529   if (hasIntGen) {
00530      hf << "  Int_t getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const;" << endl
00531         << "  void initGenerator(Int_t code) {} ; // optional pre-generation initialization" << endl
00532         << "  void generateEvent(Int_t code);" << endl
00533         << endl ;
00534   }
00535 
00536   hf << "protected:" << endl
00537      << "" << endl ;
00538 
00539   // Insert list of input arguments
00540   for (i=0 ; i<alist.size() ; i++) {
00541     if (!isCat[i]) {
00542       hf << "  RooRealProxy " << alist[i] << " ;" << endl ;
00543     } else {
00544       hf << "  RooCategoryProxy " << alist[i] << " ;" << endl ;
00545     }
00546   }
00547 
00548   hf << "  " << endl
00549      << "  Double_t evaluate() const ;" << endl
00550      << "" << endl
00551      << "private:" << endl
00552      << "" << endl
00553      << "  ClassDef(" << className << ",1) // Your description goes here..." << endl
00554      << "};" << endl
00555      << " " << endl
00556      << "#endif" << endl ;
00557 
00558 
00559   ofstream cf(impFileName) ;
00560 
00561   cf << "/***************************************************************************** " << endl
00562      << " * Project: RooFit                                                           * " << endl
00563      << " *                                                                           * " << endl
00564      << " * This code was autogenerated by RooClassFactory                            * " << endl
00565      << " *****************************************************************************/ " << endl
00566      << endl
00567      << "// Your description goes here... " << endl
00568      << endl
00569 
00570      << "#include \"Riostream.h\" " << endl
00571      << endl
00572 
00573      << "#include \"" << className << ".h\" " << endl
00574      << "#include \"RooAbsReal.h\" " << endl
00575      << "#include \"RooAbsCategory.h\" " << endl
00576      << "#include <math.h> " << endl
00577      << "#include \"TMath.h\" " << endl
00578      << endl
00579 
00580      << "ClassImp(" << className << ") " << endl
00581      << endl
00582 
00583      << " " << className << "::" << className << "(const char *name, const char *title, " << endl ;
00584 
00585   // Insert list of proxy constructors
00586   for (i=0 ; i<alist.size() ; i++) {
00587     if (!isCat[i]) {
00588       cf << "                        RooAbsReal& _" << alist[i] ;
00589     } else {
00590       cf << "                        RooAbsCategory& _" << alist[i] ;
00591     }
00592     if (i<alist.size()-1) {
00593       cf << "," ;
00594     } else {
00595       cf << ") :" ;
00596     }
00597     cf << endl ;
00598   }
00599 
00600   // Insert base class constructor
00601   cf << "   " << baseName << "(name,title), " << endl ;
00602 
00603   // Insert list of proxy constructors
00604   for (i=0 ; i<alist.size() ; i++) {
00605     cf << "   " << alist[i] << "(\"" << alist[i] << "\",\"" << alist[i] << "\",this,_" << alist[i] << ")" ;
00606     if (i<alist.size()-1) {
00607       cf << "," ;
00608     }
00609     cf << endl ;
00610   }
00611 
00612   cf << " { " << endl
00613      << " } " << endl
00614      << endl
00615      << endl
00616 
00617      << " " << className << "::" << className << "(const " << className << "& other, const char* name) :  " << endl
00618      << "   " << baseName << "(other,name), " << endl ;
00619 
00620   for (i=0 ; i<alist.size() ; i++) {
00621     cf << "   " << alist[i] << "(\"" << alist[i] << "\",this,other." << alist[i] << ")" ;
00622     if (i<alist.size()-1) {
00623       cf << "," ;
00624     }
00625     cf << endl ;
00626   }
00627 
00628   cf << " { " << endl
00629      << " } " << endl
00630      << endl
00631      << endl
00632      << endl
00633 
00634      << " Double_t " << className << "::evaluate() const " << endl
00635      << " { " << endl
00636      << "   // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE " << endl
00637      << "   return " << expression << " ; " << endl
00638      << " } " << endl
00639      << endl
00640      << endl
00641      << endl ;
00642 
00643   if (hasAnaInt) {
00644 
00645     vector<string> intObs ;
00646     vector<string> intExpr ;
00647     // Parse analytical integration expression if provided
00648     // Expected form is observable:expression,observable,observable:expression;[...]
00649     if (intExpression && *intExpression) {
00650       char* buf = new char[strlen(intExpression)+1] ;
00651       strlcpy(buf,intExpression,strlen(intExpression)+1) ;
00652       char* ptr = strtok(buf,":") ;
00653       while(ptr) {
00654         intObs.push_back(ptr) ;
00655         intExpr.push_back(strtok(0,";")) ;
00656         ptr = strtok(0,":") ;
00657       }
00658       delete[] buf ;
00659     }
00660 
00661     cf << " Int_t " << className << "::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const  " << endl
00662        << " { " << endl
00663        << "   // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED, " << endl
00664        << "   // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
00665        << "   // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
00666        << "   // YOU CAN ALSO IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs " << endl
00667        << "   // EXPRESSION MULTIPLE TIMES" << endl
00668        << endl  ;
00669 
00670     if (intObs.size()>0) {
00671       for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
00672         cf << "   if (matchArgs(allVars,analVars," << intObs[ii] << ")) return " << ii+1 << " ; " << endl ;
00673       }
00674     } else {
00675       cf << "   // if (matchArgs(allVars,analVars,x)) return 1 ; " << endl ;
00676     }
00677 
00678     cf << "   return 0 ; " << endl
00679        << " } " << endl
00680        << endl
00681        << endl
00682        << endl
00683 
00684        << " Double_t " << className << "::analyticalIntegral(Int_t code, const char* rangeName) const  " << endl
00685        << " { " << endl
00686        << "   // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY getAnalyticalIntegral" << endl
00687        << "   // THE MEMBER FUNCTION x.min(rangeName) AND x.max(rangeName) WILL RETURN THE INTEGRATION" << endl
00688        << "   // BOUNDARIES FOR EACH OBSERVABLE x" << endl
00689        << endl ;
00690 
00691     if (intObs.size()>0) {
00692       for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
00693         cf << "   if (code==" << ii+1 << ") { return (" << intExpr[ii] << ") ; } " << endl ;
00694       }
00695     } else {
00696       cf << "   // assert(code==1) ; " << endl
00697          << "   // return (x.max(rangeName)-x.min(rangeName)) ; " << endl ;
00698     }
00699 
00700     cf << "   return 0 ; " << endl
00701        << " } " << endl
00702        << endl
00703        << endl
00704        << endl ;
00705   }
00706 
00707   if (hasIntGen) {
00708     cf << " Int_t " << className << "::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const " << endl
00709        << " { " << endl
00710        << "   // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, " << endl
00711        << "   // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
00712        << "   // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
00713        << "   // YOU CAN ALSO IMPLEMENT MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs " << endl
00714        << "   // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE THEN IT IS SAFE TO PRECALCULATE " << endl
00715        << "   // INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS NOT SET THEN YOU SHOULD NOT ADVERTISE" << endl
00716        << "   // ANY GENERATOR METHOD THAT RELIES ON PRECALCULATIONS IN initGenerator()" << endl
00717        << endl
00718        << "   // if (matchArgs(directVars,generateVars,x)) return 1 ;   " << endl
00719        << "   return 0 ; " << endl
00720        << " } " << endl
00721        << endl
00722        << endl
00723        << endl
00724 
00725        << " void " << className << "::generateEvent(Int_t code) " << endl
00726        << " { " << endl
00727        << "   // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY getGenerator()" << endl
00728        << "   // RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE PROXY DATA MEMBERS THAT" << endl
00729        << "   // REPRESENT THE CHOSEN OBSERVABLES" << endl
00730        << endl
00731        << "   // assert(code==1) ; " << endl
00732        << "   // x = 0 ; " << endl
00733        << "   return; " << endl
00734        << " } " << endl
00735        << endl
00736        << endl
00737        << endl ;
00738   }
00739 
00740 
00741   return kFALSE ;
00742 }
00743 
00744 //_____________________________________________________________________________
00745 std::string RooClassFactory::ClassFacIFace::create(RooFactoryWSTool& ft, const char* typeName, const char* instanceName, std::vector<std::string> args)
00746 {
00747   static int classCounter = 0 ;
00748 
00749   string tn(typeName) ;
00750   if (tn=="CEXPR" || tn=="cexpr") {
00751 
00752     if (args.size()<2) {
00753       throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 arguments (expr,var,...), but only %u args found",
00754                         (UInt_t)args.size())) ;
00755     }
00756 
00757     RooAbsArg* ret ;
00758     // Strip quotation marks from expression string
00759     char expr[1024] ;
00760     strncpy(expr,args[0].c_str()+1,args[0].size()-2) ;
00761     expr[args[0].size()-2]=0 ;
00762 
00763 
00764     RooArgList varList ;
00765 
00766     try {
00767       if (args.size()==2) {
00768         // Interpret 2nd arg as list
00769         varList.add(ft.asLIST(args[1].c_str())) ;
00770       } else {
00771         for (unsigned int i=1 ; i<args.size() ; i++) {
00772           varList.add(ft.asARG(args[i].c_str())) ;
00773         }
00774       }
00775     } catch (string err) {
00776       throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: %s",err.c_str())) ;
00777     }
00778 
00779     string className ;
00780     while(true) {
00781       className = Form("RooCFAuto%03d%s",classCounter,(tn=="CEXPR")?"Pdf":"Func") ;
00782       TClass* tc =  TClass::GetClass(className.c_str(),kTRUE,kTRUE) ;
00783       classCounter++ ;
00784       if (!tc) {
00785         break ;
00786       }
00787     }
00788 
00789     if (tn=="CEXPR") {
00790       ret = makePdfInstance(className.c_str(),instanceName,expr,varList) ;
00791     } else {
00792       ret = makeFunctionInstance(className.c_str(),instanceName,expr,varList) ;
00793     }
00794     if (!ret) {
00795       throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",((tn=="CEXPR")?"pdf":"function"),instanceName)) ;
00796     }
00797 
00798     // Import object
00799     ft.ws().import(*ret,RooFit::Silence()) ;
00800 
00801     // Import class code as well
00802     ft.ws().importClassCode(ret->IsA()) ;
00803 
00804 
00805   } else {
00806 
00807     throw string(Form("RooClassFactory::ClassFacIFace::create() ERROR: Unknown meta-type %s requested",typeName)) ;
00808 
00809   }
00810   return string(instanceName) ;
00811 }

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