45 ClassImp(RooClassFactory);
50 static Int_t dummy = init() ;
54 RooFactoryWSTool::IFace* iface =
new RooClassFactory::ClassFacIFace ;
55 RooFactoryWSTool::registerSpecial(
"CEXPR",iface) ;
56 RooFactoryWSTool::registerSpecial(
"cexpr",iface) ;
67 RooClassFactory::RooClassFactory()
76 RooClassFactory::~RooClassFactory()
84 Bool_t RooClassFactory::makeAndCompilePdf(
const char* name,
const char* expression,
const RooArgList& vars,
const char* intExpression)
86 string realArgNames,catArgNames ;
87 TIterator* iter = vars.createIterator() ;
89 while((arg=(RooAbsArg*)iter->Next())) {
90 if (dynamic_cast<RooAbsReal*>(arg)) {
91 if (realArgNames.size()>0) realArgNames +=
"," ;
92 realArgNames += arg->GetName() ;
93 }
else if (dynamic_cast<RooAbsCategory*>(arg)) {
94 if (catArgNames.size()>0) catArgNames +=
"," ;
95 catArgNames += arg->GetName() ;
97 oocoutE((RooAbsArg*)0,InputArguments) <<
"RooClassFactory::makeAndCompilePdf ERROR input argument " << arg->GetName()
98 <<
" is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
103 Bool_t ret = makePdf(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,kFALSE,intExpression) ;
108 TInterpreter::EErrorCode ecode;
109 gInterpreter->ProcessLineSynch(Form(
".L %s.cxx+",name),&ecode) ;
110 return (ecode!=TInterpreter::kNoError) ;
128 Bool_t RooClassFactory::makeAndCompileFunction(
const char* name,
const char* expression,
const RooArgList& vars,
const char* intExpression)
130 string realArgNames,catArgNames ;
131 TIterator* iter = vars.createIterator() ;
133 while((arg=(RooAbsArg*)iter->Next())) {
134 if (dynamic_cast<RooAbsReal*>(arg)) {
135 if (realArgNames.size()>0) realArgNames +=
"," ;
136 realArgNames += arg->GetName() ;
137 }
else if (dynamic_cast<RooAbsCategory*>(arg)) {
138 if (catArgNames.size()>0) catArgNames +=
"," ;
139 catArgNames += arg->GetName() ;
141 oocoutE((RooAbsArg*)0,InputArguments) <<
"RooClassFactory::makeAndCompileFunction ERROR input argument " << arg->GetName()
142 <<
" is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
147 Bool_t ret = makeFunction(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,intExpression) ;
152 TInterpreter::EErrorCode ecode;
153 gInterpreter->ProcessLineSynch(Form(
".L %s.cxx+",name),&ecode) ;
154 return (ecode!=TInterpreter::kNoError) ;
178 RooAbsReal* RooClassFactory::makeFunctionInstance(
const char* name,
const char* expression,
const RooArgList& vars,
const char* intExpression)
181 string tmpName(name) ;
182 tmpName[0] = toupper(tmpName[0]) ;
183 string className = Form(
"Roo%sFunc",tmpName.c_str()) ;
185 return makeFunctionInstance(className.c_str(),name,expression,vars,intExpression) ;
208 RooAbsReal* RooClassFactory::makeFunctionInstance(
const char* className,
const char* name,
const char* expression,
const RooArgList& vars,
const char* intExpression)
211 Bool_t error = makeAndCompileFunction(className,expression,vars,intExpression) ;
215 RooErrorHandler::softAbort() ;
219 string line = Form(
"new %s(\"%s\",\"%s\"",className,name,name) ;
225 TIterator* iter = vars.createIterator() ;
229 while((var=(RooAbsArg*)iter->Next())) {
230 if (dynamic_cast<RooAbsReal*>(var)) {
231 argList += Form(
",*((RooAbsReal*)0x%lx)",(ULong_t)var) ;
236 while((var=(RooAbsArg*)iter->Next())) {
237 if (dynamic_cast<RooAbsCategory*>(var)) {
238 argList += Form(
",*((RooAbsCategory*)0x%lx)",(ULong_t)var) ;
243 line += argList +
") ;" ;
246 return (RooAbsReal*) gInterpreter->ProcessLineSynch(line.c_str()) ;
272 RooAbsPdf* RooClassFactory::makePdfInstance(
const char* name,
const char* expression,
273 const RooArgList& vars,
const char* intExpression)
276 string tmpName(name) ;
277 tmpName[0] = toupper(tmpName[0]) ;
278 string className = Form(
"Roo%sPdf",tmpName.c_str()) ;
280 return makePdfInstance(className.c_str(),name,expression,vars,intExpression) ;
303 RooAbsPdf* RooClassFactory::makePdfInstance(
const char* className,
const char* name,
const char* expression,
304 const RooArgList& vars,
const char* intExpression)
307 Bool_t error = makeAndCompilePdf(className,expression,vars,intExpression) ;
311 RooErrorHandler::softAbort() ;
315 string line = Form(
"new %s(\"%s\",\"%s\"",className,name,name) ;
321 TIterator* iter = vars.createIterator() ;
325 while((var=(RooAbsArg*)iter->Next())) {
326 if (dynamic_cast<RooAbsReal*>(var)) {
327 argList += Form(
",*((RooAbsReal*)0x%lx)",(ULong_t)var) ;
332 while((var=(RooAbsArg*)iter->Next())) {
333 if (dynamic_cast<RooAbsCategory*>(var)) {
334 argList += Form(
",*((RooAbsCategory*)0x%lx)",(ULong_t)var) ;
339 line += argList +
") ;" ;
342 return (RooAbsPdf*) gInterpreter->ProcessLineSynch(line.c_str()) ;
365 Bool_t RooClassFactory::makePdf(
const char* name,
const char* argNames,
const char* catArgNames,
const char* expression,
366 Bool_t hasAnaInt, Bool_t hasIntGen,
const char* intExpression)
368 return makeClass(
"RooAbsPdf",name,argNames,catArgNames,expression,hasAnaInt,hasIntGen,intExpression) ;
388 Bool_t RooClassFactory::makeFunction(
const char* name,
const char* argNames,
const char* catArgNames,
const char* expression, Bool_t hasAnaInt,
const char* intExpression)
390 return makeClass(
"RooAbsReal",name,argNames,catArgNames,expression,hasAnaInt,kFALSE,intExpression) ;
412 Bool_t RooClassFactory::makeClass(
const char* baseName,
const char* className,
const char* realArgNames,
const char* catArgNames,
413 const char* expression, Bool_t hasAnaInt, Bool_t hasIntGen,
const char* intExpression)
417 oocoutE((TObject*)0,InputArguments) <<
"RooClassFactory::makeClass: ERROR: a base class name must be given" << endl ;
422 oocoutE((TObject*)0,InputArguments) <<
"RooClassFactory::makeClass: ERROR: a class name must be given" << endl ;
426 if ((!realArgNames || !*realArgNames) && (!catArgNames || !*catArgNames)) {
427 oocoutE((TObject*)0,InputArguments) <<
"RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << endl ;
431 if (intExpression && !hasAnaInt) {
432 oocoutE((TObject*)0,InputArguments) <<
"RooClassFactory::makeClass: ERROR no analytical integration code requestion, but expression for analytical integral provided" << endl ;
437 vector<string> alist ;
440 if (realArgNames && *realArgNames) {
441 const size_t bufSize = strlen(realArgNames)+1;
442 char* buf =
new char[bufSize] ;
443 strlcpy(buf,realArgNames,bufSize) ;
444 char* token = strtok(buf,
",") ;
446 alist.push_back(token) ;
447 isCat.push_back(
false) ;
448 token = strtok(0,
",") ;
452 if (catArgNames && *catArgNames) {
453 const size_t bufSize = strlen(catArgNames)+1;
454 char* buf =
new char[bufSize] ;
455 strlcpy(buf,catArgNames,bufSize) ;
456 char* token = strtok(buf,
",") ;
458 alist.push_back(token) ;
459 isCat.push_back(
true) ;
460 token = strtok(0,
",") ;
465 TString impFileName(className), hdrFileName(className) ;
466 impFileName +=
".cxx" ;
467 hdrFileName +=
".h" ;
469 TString ifdefName(className) ;
470 ifdefName.ToUpper() ;
472 ofstream hf(hdrFileName) ;
473 hf <<
"/*****************************************************************************" << endl
474 <<
" * Project: RooFit *" << endl
476 <<
" * This code was autogenerated by RooClassFactory * " << endl
477 <<
" *****************************************************************************/" << endl
479 <<
"#ifndef " << ifdefName << endl
480 <<
"#define " << ifdefName << endl
482 <<
"#include \"" << baseName <<
".h\"" << endl
483 <<
"#include \"RooRealProxy.h\"" << endl
484 <<
"#include \"RooCategoryProxy.h\"" << endl
485 <<
"#include \"RooAbsReal.h\"" << endl
486 <<
"#include \"RooAbsCategory.h\"" << endl
488 <<
"class " << className <<
" : public " << baseName <<
" {" << endl
490 <<
" " << className <<
"() {} ; " << endl
491 <<
" " << className <<
"(const char *name, const char *title," << endl ;
495 for (i=0 ; i<alist.size() ; i++) {
497 hf <<
" RooAbsReal& _" ;
499 hf <<
" RooAbsCategory& _" ;
502 if (i==alist.size()-1) {
509 hf <<
" " << className <<
"(const " << className <<
"& other, const char* name=0) ;" << endl
510 <<
" virtual TObject* clone(const char* newname) const { return new " << className <<
"(*this,newname); }" << endl
511 <<
" inline virtual ~" << className <<
"() { }" << endl
515 hf <<
" Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;" << endl
516 <<
" Double_t analyticalIntegral(Int_t code, const char* rangeName=0) const ;" << endl
521 hf <<
" Int_t getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const;" << endl
522 <<
" void initGenerator(Int_t code) {} ; // optional pre-generation initialization" << endl
523 <<
" void generateEvent(Int_t code);" << endl
527 hf <<
"protected:" << endl
531 for (i=0 ; i<alist.size() ; i++) {
533 hf <<
" RooRealProxy " << alist[i] <<
" ;" << endl ;
535 hf <<
" RooCategoryProxy " << alist[i] <<
" ;" << endl ;
540 <<
" Double_t evaluate() const ;" << endl
542 <<
"private:" << endl
544 <<
" ClassDef(" << className <<
",1) // Your description goes here..." << endl
547 <<
"#endif" << endl ;
550 ofstream cf(impFileName) ;
552 cf <<
"/***************************************************************************** " << endl
553 <<
" * Project: RooFit * " << endl
555 <<
" * This code was autogenerated by RooClassFactory * " << endl
556 <<
" *****************************************************************************/ " << endl
558 <<
"// Your description goes here... " << endl
561 <<
"#include \"Riostream.h\" " << endl
564 <<
"#include \"" << className <<
".h\" " << endl
565 <<
"#include \"RooAbsReal.h\" " << endl
566 <<
"#include \"RooAbsCategory.h\" " << endl
567 <<
"#include <math.h> " << endl
568 <<
"#include \"TMath.h\" " << endl
571 <<
"ClassImp(" << className <<
"); " << endl
574 <<
" " << className <<
"::" << className <<
"(const char *name, const char *title, " << endl ;
577 for (i=0 ; i<alist.size() ; i++) {
579 cf <<
" RooAbsReal& _" << alist[i] ;
581 cf <<
" RooAbsCategory& _" << alist[i] ;
583 if (i<alist.size()-1) {
592 cf <<
" " << baseName <<
"(name,title), " << endl ;
595 for (i=0 ; i<alist.size() ; i++) {
596 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",\"" << alist[i] <<
"\",this,_" << alist[i] <<
")" ;
597 if (i<alist.size()-1) {
608 <<
" " << className <<
"::" << className <<
"(const " << className <<
"& other, const char* name) : " << endl
609 <<
" " << baseName <<
"(other,name), " << endl ;
611 for (i=0 ; i<alist.size() ; i++) {
612 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",this,other." << alist[i] <<
")" ;
613 if (i<alist.size()-1) {
625 <<
" Double_t " << className <<
"::evaluate() const " << endl
627 <<
" // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE " << endl
628 <<
" return " << expression <<
" ; " << endl
636 vector<string> intObs ;
637 vector<string> intExpr ;
640 if (intExpression && *intExpression) {
641 const size_t bufSize = strlen(intExpression)+1;
642 char* buf =
new char[bufSize] ;
643 strlcpy(buf,intExpression,bufSize) ;
644 char* ptr = strtok(buf,
":") ;
646 intObs.push_back(ptr) ;
647 intExpr.push_back(strtok(0,
";")) ;
648 ptr = strtok(0,
":") ;
653 cf <<
" Int_t " << className <<
"::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const " << endl
655 <<
" // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED, " << endl
656 <<
" // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
657 <<
" // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
658 <<
" // YOU CAN ALSO IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs " << endl
659 <<
" // EXPRESSION MULTIPLE TIMES" << endl
662 if (intObs.size()>0) {
663 for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
664 cf <<
" if (matchArgs(allVars,analVars," << intObs[ii] <<
")) return " << ii+1 <<
" ; " << endl ;
667 cf <<
" // if (matchArgs(allVars,analVars,x)) return 1 ; " << endl ;
670 cf <<
" return 0 ; " << endl
676 <<
" Double_t " << className <<
"::analyticalIntegral(Int_t code, const char* rangeName) const " << endl
678 <<
" // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY getAnalyticalIntegral" << endl
679 <<
" // THE MEMBER FUNCTION x.min(rangeName) AND x.max(rangeName) WILL RETURN THE INTEGRATION" << endl
680 <<
" // BOUNDARIES FOR EACH OBSERVABLE x" << endl
683 if (intObs.size()>0) {
684 for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
685 cf <<
" if (code==" << ii+1 <<
") { return (" << intExpr[ii] <<
") ; } " << endl ;
688 cf <<
" // assert(code==1) ; " << endl
689 <<
" // return (x.max(rangeName)-x.min(rangeName)) ; " << endl ;
692 cf <<
" return 0 ; " << endl
700 cf <<
" Int_t " << className <<
"::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const " << endl
702 <<
" // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, " << endl
703 <<
" // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
704 <<
" // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
705 <<
" // YOU CAN ALSO IMPLEMENT MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs " << endl
706 <<
" // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE THEN IT IS SAFE TO PRECALCULATE " << endl
707 <<
" // INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS NOT SET THEN YOU SHOULD NOT ADVERTISE" << endl
708 <<
" // ANY GENERATOR METHOD THAT RELIES ON PRECALCULATIONS IN initGenerator()" << endl
710 <<
" // if (matchArgs(directVars,generateVars,x)) return 1 ; " << endl
711 <<
" return 0 ; " << endl
717 <<
" void " << className <<
"::generateEvent(Int_t code) " << endl
719 <<
" // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY getGenerator()" << endl
720 <<
" // RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE PROXY DATA MEMBERS THAT" << endl
721 <<
" // REPRESENT THE CHOSEN OBSERVABLES" << endl
723 <<
" // assert(code==1) ; " << endl
724 <<
" // x = 0 ; " << endl
725 <<
" return; " << endl
738 std::string RooClassFactory::ClassFacIFace::create(RooFactoryWSTool& ft,
const char* typeName,
const char* instanceName, std::vector<std::string> args)
740 static int classCounter = 0 ;
742 string tn(typeName) ;
743 if (tn==
"CEXPR" || tn==
"cexpr") {
746 throw string(Form(
"RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 arguments (expr,var,...), but only %u args found",
747 (UInt_t)args.size())) ;
753 strncpy(expr,args[0].c_str()+1,args[0].size()-2) ;
754 expr[args[0].size()-2]=0 ;
760 if (args.size()==2) {
762 varList.add(ft.asLIST(args[1].c_str())) ;
764 for (
unsigned int i=1 ; i<args.size() ; i++) {
765 varList.add(ft.asARG(args[i].c_str())) ;
768 }
catch (
const string &err) {
769 throw string(Form(
"RooClassFactory::ClassFacIFace::create() ERROR: %s",err.c_str())) ;
774 className = Form(
"RooCFAuto%03d%s%s",classCounter,(tn==
"CEXPR")?
"Pdf":
"Func",ft.autoClassNamePostFix()) ;
775 TClass* tc = TClass::GetClass(className.c_str(),kTRUE,kTRUE) ;
783 ret = makePdfInstance(className.c_str(),instanceName,expr,varList) ;
785 ret = makeFunctionInstance(className.c_str(),instanceName,expr,varList) ;
788 throw string(Form(
"RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",((tn==
"CEXPR")?
"pdf":
"function"),instanceName)) ;
792 ft.ws().import(*ret,RooFit::Silence()) ;
795 ft.ws().importClassCode(ret->IsA()) ;
800 throw string(Form(
"RooClassFactory::ClassFacIFace::create() ERROR: Unknown meta-type %s requested",typeName)) ;
803 return string(instanceName) ;