// RooClassFactory is a clase like TTree::MakeClass() that generates
// skeleton code for RooAbsPdf and RooAbsReal functions given
// a list of input parameter names. The factory can also compile
// the generated code on the fly, and on request also immediate
// instantiate objects.
// END_HTML
#include "RooFit.h"
#include "RooClassFactory.h"
#include "RooClassFactory.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooArgList.h"
#include "RooMsgService.h"
#include "TInterpreter.h"
#include <fstream>
#include <vector>
#include <string>
using namespace std ;
ClassImp(RooClassFactory)
;
RooClassFactory::RooClassFactory()
{
}
RooClassFactory::~RooClassFactory()
{
}
Bool_t RooClassFactory::makeAndCompilePdf(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
{
string realArgNames,catArgNames ;
TIterator* iter = vars.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsReal*>(arg)) {
if (realArgNames.size()>0) realArgNames += "," ;
realArgNames += arg->GetName() ;
} else if (dynamic_cast<RooAbsCategory*>(arg)) {
if (catArgNames.size()>0) catArgNames += "," ;
catArgNames += arg->GetName() ;
} else {
oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompilePdf ERROR input argument " << arg->GetName()
<< " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
}
}
delete iter ;
Bool_t ret = makePdf(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,kFALSE,intExpression) ;
if (ret) {
return ret ;
}
if (gInterpreter->GetRootMapFiles()==0) {
gInterpreter->EnableAutoLoading() ;
}
TInterpreter::EErrorCode ecode;
gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
return (ecode!=TInterpreter::kNoError) ;
}
Bool_t RooClassFactory::makeAndCompileFunction(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
{
string realArgNames,catArgNames ;
TIterator* iter = vars.createIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsReal*>(arg)) {
if (realArgNames.size()>0) realArgNames += "," ;
realArgNames += arg->GetName() ;
} else if (dynamic_cast<RooAbsCategory*>(arg)) {
if (catArgNames.size()>0) catArgNames += "," ;
catArgNames += arg->GetName() ;
} else {
oocoutE((RooAbsArg*)0,InputArguments) << "RooClassFactory::makeAndCompileFunction ERROR input argument " << arg->GetName()
<< " is neither RooAbsReal nor RooAbsCategory and is ignored" << endl ;
}
}
delete iter ;
Bool_t ret = makeFunction(name,realArgNames.c_str(),catArgNames.c_str(),expression,intExpression?kTRUE:kFALSE,intExpression) ;
if (ret) {
return ret ;
}
if (gInterpreter->GetRootMapFiles()==0) {
gInterpreter->EnableAutoLoading() ;
}
TInterpreter::EErrorCode ecode;
gInterpreter->ProcessLineSynch(Form(".L %s.cxx+",name),&ecode) ;
return (ecode!=TInterpreter::kNoError) ;
}
RooAbsReal* RooClassFactory::makeFunctionInstance(const char* name, const char* expression, const RooArgList& vars, const char* intExpression)
{
if (gInterpreter->GetRootMapFiles()==0) {
gInterpreter->EnableAutoLoading() ;
}
string className = Form("Roo%sClass",name) ;
Bool_t error = makeAndCompileFunction(className.c_str(),expression,vars,intExpression) ;
if (error) {
RooErrorHandler::softAbort() ;
}
string line = Form("new %s(\"%s\",\"%s\"",className.c_str(),name,name) ;
TIterator* iter = vars.createIterator() ;
string argList ;
RooAbsArg* var ;
while((var=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsReal*>(var)) {
argList += Form(",*((RooAbsReal*)%p)",var) ;
}
}
iter->Reset() ;
while((var=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsCategory*>(var)) {
argList += Form(",*((RooAbsCategory*)%p)",var) ;
}
}
delete iter ;
line += argList + ") " ;
return (RooAbsReal*) gInterpreter->ProcessLineSynch(line.c_str()) ;
}
RooAbsPdf* RooClassFactory::makePdfInstance(const char* name, const char* expression,
const RooArgList& vars, const char* intExpression)
{
if (gInterpreter->GetRootMapFiles()==0) {
gInterpreter->EnableAutoLoading() ;
}
string className = Form("Roo%sClass",name) ;
Bool_t error = makeAndCompilePdf(className.c_str(),expression,vars,intExpression) ;
if (error) {
RooErrorHandler::softAbort() ;
}
string line = Form("new %s(\"%s\",\"%s\"",className.c_str(),name,name) ;
TIterator* iter = vars.createIterator() ;
string argList ;
RooAbsArg* var ;
while((var=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsReal*>(var)) {
argList += Form(",*((RooAbsReal*)%p)",var) ;
}
}
iter->Reset() ;
while((var=(RooAbsArg*)iter->Next())) {
if (dynamic_cast<RooAbsCategory*>(var)) {
argList += Form(",*((RooAbsCategory*)%p)",var) ;
}
}
delete iter ;
line += argList + ") " ;
return (RooAbsPdf*) gInterpreter->ProcessLineSynch(line.c_str()) ;
}
Bool_t RooClassFactory::makePdf(const char* name, const char* argNames, const char* catArgNames, const char* expression,
Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
{
return makeClass("RooAbsPdf",name,argNames,catArgNames,expression,hasAnaInt,hasIntGen,intExpression) ;
}
Bool_t RooClassFactory::makeFunction(const char* name, const char* argNames, const char* catArgNames, const char* expression, Bool_t hasAnaInt, const char* intExpression)
{
return makeClass("RooAbsReal",name,argNames,catArgNames,expression,hasAnaInt,kFALSE,intExpression) ;
}
Bool_t RooClassFactory::makeClass(const char* baseName, const char* className, const char* realArgNames, const char* catArgNames,
const char* expression, Bool_t hasAnaInt, Bool_t hasIntGen, const char* intExpression)
{
if (!baseName) {
oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a base class name must be given" << endl ;
return kTRUE ;
}
if (!className) {
oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: a class name must be given" << endl ;
return kTRUE ;
}
if ((!realArgNames || !*realArgNames) && (!catArgNames || !*catArgNames)) {
oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << endl ;
return kTRUE ;
}
if (intExpression && !hasAnaInt) {
oocoutE((TObject*)0,InputArguments) << "RooClassFactory::makeClass: ERROR no analytical integration code requestion, but expression for analytical integral provided" << endl ;
return kTRUE ;
}
vector<string> alist ;
vector<bool> isCat ;
if (realArgNames && *realArgNames) {
char* buf = new char[strlen(realArgNames)+1] ;
strcpy(buf,realArgNames) ;
char* token = strtok(buf,",") ;
while(token) {
alist.push_back(token) ;
isCat.push_back(false) ;
token = strtok(0,",") ;
}
delete[] buf ;
}
if (catArgNames && *catArgNames) {
char* buf = new char[strlen(catArgNames)+1] ;
strcpy(buf,catArgNames) ;
char* token = strtok(buf,",") ;
while(token) {
alist.push_back(token) ;
isCat.push_back(true) ;
token = strtok(0,",") ;
}
delete[] buf ;
}
TString impFileName(className), hdrFileName(className) ;
impFileName += ".cxx" ;
hdrFileName += ".h" ;
TString ifdefName(className) ;
ifdefName.ToUpper() ;
ofstream hf(hdrFileName) ;
hf << "/*****************************************************************************" << endl
<< " * Project: RooFit *" << endl
<< " * *" << endl
<< " * This code was autogenerated by RooClassFactory * " << endl
<< " *****************************************************************************/" << endl
<< endl
<< "#ifndef " << ifdefName << endl
<< "#define " << ifdefName << endl
<< "" << endl
<< "#include \"" << baseName << ".h\"" << endl
<< "#include \"RooRealProxy.h\"" << endl
<< "#include \"RooCategoryProxy.h\"" << endl
<< "#include \"RooAbsReal.h\"" << endl
<< "#include \"RooAbsCategory.h\"" << endl
<< " " << endl
<< "class " << className << " : public " << baseName << " {" << endl
<< "public:" << endl
<< " " << className << "() {} ; " << endl
<< " " << className << "(const char *name, const char *title," << endl ;
unsigned int i ;
for (i=0 ; i<alist.size() ; i++) {
if (!isCat[i]) {
hf << " RooAbsReal& _" ;
} else {
hf << " RooAbsCategory& _" ;
}
hf << alist[i] ;
if (i==alist.size()-1) {
hf << ");" << endl ;
} else {
hf << "," << endl ;
}
}
hf << " " << className << "(const " << className << "& other, const char* name=0) ;" << endl
<< " virtual TObject* clone(const char* newname) const { return new " << className << "(*this,newname); }" << endl
<< " inline virtual ~" << className << "() { }" << endl
<< endl ;
if (hasAnaInt) {
hf << " Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName=0) const ;" << endl
<< " Double_t analyticalIntegral(Int_t code, const char* rangeName=0) const ;" << endl
<< "" << endl ;
}
if (hasIntGen) {
hf << " Int_t getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const;" << endl
<< " void initGenerator(Int_t code) {} ; // optional pre-generation initialization" << endl
<< " void generateEvent(Int_t code);" << endl
<< endl ;
}
hf << "protected:" << endl
<< "" << endl ;
for (i=0 ; i<alist.size() ; i++) {
if (!isCat[i]) {
hf << " RooRealProxy " << alist[i] << " ;" << endl ;
} else {
hf << " RooCategoryProxy " << alist[i] << " ;" << endl ;
}
}
hf << " " << endl
<< " Double_t evaluate() const ;" << endl
<< "" << endl
<< "private:" << endl
<< "" << endl
<< " ClassDef(" << className << ",1) // Your description goes here..." << endl
<< "};" << endl
<< " " << endl
<< "#endif" << endl ;
ofstream cf(impFileName) ;
cf << " /***************************************************************************** " << endl
<< " * Project: RooFit * " << endl
<< " * * " << endl
<< " * This code was autogenerated by RooClassFactory * " << endl
<< " *****************************************************************************/ " << endl
<< endl
<< " // Your description goes here... " << endl
<< endl
<< " #include \"Riostream.h\" " << endl
<< endl
<< " #include \"" << className << ".h\" " << endl
<< " #include \"RooAbsReal.h\" " << endl
<< " #include \"RooAbsCategory.h\" " << endl
<< endl
<< " ClassImp(" << className << ") " << endl
<< endl
<< " " << className << "::" << className << "(const char *name, const char *title, " << endl ;
for (i=0 ; i<alist.size() ; i++) {
if (!isCat[i]) {
cf << " RooAbsReal& _" << alist[i] ;
} else {
cf << " RooAbsCategory& _" << alist[i] ;
}
if (i<alist.size()-1) {
cf << "," ;
} else {
cf << ") :" ;
}
cf << endl ;
}
cf << " " << baseName << "(name,title), " << endl ;
for (i=0 ; i<alist.size() ; i++) {
cf << " " << alist[i] << "(\"" << alist[i] << "\",\"" << alist[i] << "\",this,_" << alist[i] << ")" ;
if (i<alist.size()-1) {
cf << "," ;
}
cf << endl ;
}
cf << " { " << endl
<< " } " << endl
<< endl
<< endl
<< " " << className << "::" << className << "(const " << className << "& other, const char* name) : " << endl
<< " " << baseName << "(other,name), " << endl ;
for (i=0 ; i<alist.size() ; i++) {
cf << " " << alist[i] << "(\"" << alist[i] << "\",this,other." << alist[i] << ")" ;
if (i<alist.size()-1) {
cf << "," ;
}
cf << endl ;
}
cf << " { " << endl
<< " } " << endl
<< endl
<< endl
<< endl
<< " Double_t " << className << "::evaluate() const " << endl
<< " { " << endl
<< " // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE " << endl
<< " return " << expression << " ; " << endl
<< " } " << endl
<< endl
<< endl
<< endl ;
if (hasAnaInt) {
vector<string> intObs ;
vector<string> intExpr ;
if (intExpression && *intExpression) {
char* buf = new char[strlen(intExpression)+1] ;
strcpy(buf,intExpression) ;
char* ptr = strtok(buf,":") ;
while(ptr) {
intObs.push_back(ptr) ;
intExpr.push_back(strtok(0,";")) ;
ptr = strtok(0,":") ;
}
delete[] buf ;
}
cf << " Int_t " << className << "::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const " << endl
<< " { " << endl
<< " // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED, " << endl
<< " // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
<< " // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
<< " // YOU CAN ALSO IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs " << endl
<< " // EXPRESSION MULTIPLE TIMES" << endl
<< endl ;
if (intObs.size()>0) {
for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
cf << " if (matchArgs(allVars,analVars," << intObs[ii] << ")) return " << ii+1 << " ; " << endl ;
}
} else {
cf << " // if (matchArgs(allVars,analVars,x)) return 1 ; " << endl ;
}
cf << " return 0 ; " << endl
<< " } " << endl
<< endl
<< endl
<< endl
<< " Double_t " << className << "::analyticalIntegral(Int_t code, const char* rangeName) const " << endl
<< " { " << endl
<< " // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY getAnalyticalIntegral" << endl
<< " // THE MEMBER FUNCTION x.min(rangeName) AND x.max(rangeName) WILL RETURN THE INTEGRATION" << endl
<< " // BOUNDARIES FOR EACH OBSERVABLE x" << endl
<< endl ;
if (intObs.size()>0) {
for (UInt_t ii=0 ; ii<intObs.size() ; ii++) {
cf << " if (code==" << ii+1 << ") { return (" << intExpr[ii] << ") ; } " << endl ;
}
} else {
cf << " // assert(code==1) ; " << endl
<< " // return (x.max(rangeName)-x.min(rangeName)) ; " << endl ;
}
cf << " return 0 ; " << endl
<< " } " << endl
<< endl
<< endl
<< endl ;
}
if (hasIntGen) {
cf << " Int_t " << className << "::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const " << endl
<< " { " << endl
<< " // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, " << endl
<< " // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS " << endl
<< " // THE EXAMPLE BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X" << endl
<< " // YOU CAN ALSO IMPLEMENT MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs " << endl
<< " // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE THEN IT IS SAFE TO PRECALCULATE " << endl
<< " // INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS NOT SET THEN YOU SHOULD NOT ADVERTISE" << endl
<< " // ANY GENERATOR METHOD THAT RELIES ON PRECALCULATIONS IN initGenerator()" << endl
<< endl
<< " // if (matchArgs(directVars,generateVars,x)) return 1 ; " << endl
<< " return 0 ; " << endl
<< " } " << endl
<< endl
<< endl
<< endl
<< " void " << className << "::generateEvent(Int_t code) " << endl
<< " { " << endl
<< " // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY getGenerator()" << endl
<< " // RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE PROXY DATA MEMBERS THAT" << endl
<< " // REPRESENT THE CHOSEN OBSERVABLES" << endl
<< endl
<< " // assert(code==1) ; " << endl
<< " // x = 0 ; " << endl
<< " return; " << endl
<< " } " << endl
<< endl
<< endl
<< endl ;
}
return kFALSE ;
}
Last change: Wed Jun 25 08:32:22 2008
Last generated: 2008-06-25 08:32
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.